summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/amcheck/verify_nbtree.c1
-rw-r--r--contrib/pg_visibility/pg_visibility.c2
-rw-r--r--src/backend/access/nbtree/nbtsort.c1
-rw-r--r--src/backend/replication/logical/snapbuild.c6
-rw-r--r--src/backend/utils/time/snapmgr.c10
-rw-r--r--src/backend/utils/time/tqual.c86
-rw-r--r--src/include/storage/bufmgr.h5
-rw-r--r--src/include/utils/snapshot.h90
-rw-r--r--src/include/utils/tqual.h40
-rw-r--r--src/tools/pgindent/typedefs.list2
10 files changed, 161 insertions, 82 deletions
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 1c7466c8158..c976f947a02 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -36,6 +36,7 @@
#include "storage/lmgr.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
+#include "utils/tqual.h"
PG_MODULE_MAGIC;
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 22adca18e64..d8125f1ba2f 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -21,6 +21,8 @@
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/rel.h"
+#include "utils/snapmgr.h"
+#include "utils/tqual.h"
PG_MODULE_MAGIC;
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index dc398e11867..a3e22dd51c3 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -72,6 +72,7 @@
#include "utils/rel.h"
#include "utils/sortsupport.h"
#include "utils/tuplesort.h"
+#include "utils/tqual.h"
/* Magic numbers for parallel state sharing */
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 40534824200..3e48beaa22f 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -376,7 +376,7 @@ static void
SnapBuildFreeSnapshot(Snapshot snap)
{
/* make sure we don't get passed an external snapshot */
- Assert(snap->satisfies == HeapTupleSatisfiesHistoricMVCC);
+ Assert(snap->snapshot_type == SNAPSHOT_HISTORIC_MVCC);
/* make sure nobody modified our snapshot */
Assert(snap->curcid == FirstCommandId);
@@ -434,7 +434,7 @@ void
SnapBuildSnapDecRefcount(Snapshot snap)
{
/* make sure we don't get passed an external snapshot */
- Assert(snap->satisfies == HeapTupleSatisfiesHistoricMVCC);
+ Assert(snap->snapshot_type == SNAPSHOT_HISTORIC_MVCC);
/* make sure nobody modified our snapshot */
Assert(snap->curcid == FirstCommandId);
@@ -476,7 +476,7 @@ SnapBuildBuildSnapshot(SnapBuild *builder)
snapshot = MemoryContextAllocZero(builder->context, ssize);
- snapshot->satisfies = HeapTupleSatisfiesHistoricMVCC;
+ snapshot->snapshot_type = SNAPSHOT_HISTORIC_MVCC;
/*
* We misuse the original meaning of SnapshotData's xip and subxip fields
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index f93b37b9c93..d47d2b3ef7a 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -141,9 +141,9 @@ static volatile OldSnapshotControlData *oldSnapshotControl;
* These SnapshotData structs are static to simplify memory allocation
* (see the hack in GetSnapshotData to avoid repeated malloc/free).
*/
-static SnapshotData CurrentSnapshotData = {HeapTupleSatisfiesMVCC};
-static SnapshotData SecondarySnapshotData = {HeapTupleSatisfiesMVCC};
-SnapshotData CatalogSnapshotData = {HeapTupleSatisfiesMVCC};
+static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC};
+static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC};
+SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC};
/* Pointers to valid snapshots */
static Snapshot CurrentSnapshot = NULL;
@@ -2046,7 +2046,7 @@ EstimateSnapshotSpace(Snapshot snap)
Size size;
Assert(snap != InvalidSnapshot);
- Assert(snap->satisfies == HeapTupleSatisfiesMVCC);
+ Assert(snap->snapshot_type == SNAPSHOT_MVCC);
/* We allocate any XID arrays needed in the same palloc block. */
size = add_size(sizeof(SerializedSnapshotData),
@@ -2143,7 +2143,7 @@ RestoreSnapshot(char *start_address)
/* Copy all required fields */
snapshot = (Snapshot) MemoryContextAlloc(TopTransactionContext, size);
- snapshot->satisfies = HeapTupleSatisfiesMVCC;
+ snapshot->snapshot_type = SNAPSHOT_MVCC;
snapshot->xmin = serialized_snapshot.xmin;
snapshot->xmax = serialized_snapshot.xmax;
snapshot->xip = NULL;
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index edd4f7e36c6..3a44ccae3c9 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -78,8 +78,8 @@
/* Static variables representing various special snapshot semantics */
-SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
-SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
+SnapshotData SnapshotSelfData = {SNAPSHOT_SELF};
+SnapshotData SnapshotAnyData = {SNAPSHOT_ANY};
/*
@@ -152,10 +152,7 @@ HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
* HeapTupleSatisfiesSelf
* True iff heap tuple is valid "for itself".
*
- * Here, we consider the effects of:
- * all committed transactions (as of the current instant)
- * previous commands of this transaction
- * changes made by the current command
+ * See SNAPSHOT_MVCC's definition for the intended behaviour.
*
* Note:
* Assumes heap tuple is valid.
@@ -172,7 +169,7 @@ HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
* (Xmax != my-transaction && the row was deleted by another transaction
* Xmax is not committed))) that has not been committed
*/
-bool
+static bool
HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
{
HeapTupleHeader tuple = htup->t_data;
@@ -342,7 +339,7 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
* HeapTupleSatisfiesAny
* Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
*/
-bool
+static bool
HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
{
return true;
@@ -352,6 +349,8 @@ HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
* HeapTupleSatisfiesToast
* True iff heap tuple is valid as a TOAST row.
*
+ * See SNAPSHOT_TOAST's definition for the intended behaviour.
+ *
* This is a simplified version that only checks for VACUUM moving conditions.
* It's appropriate for TOAST usage because TOAST really doesn't want to do
* its own time qual checks; if you can see the main table row that contains
@@ -362,7 +361,7 @@ HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
* Among other things, this means you can't do UPDATEs of rows in a TOAST
* table.
*/
-bool
+static bool
HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
Buffer buffer)
{
@@ -716,10 +715,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
* HeapTupleSatisfiesDirty
* True iff heap tuple is valid including effects of open transactions.
*
- * Here, we consider the effects of:
- * all committed and in-progress transactions (as of the current instant)
- * previous commands of this transaction
- * changes made by the current command
+ * See SNAPSHOT_DIRTY's definition for the intended behaviour.
*
* This is essentially like HeapTupleSatisfiesSelf as far as effects of
* the current transaction and committed/aborted xacts are concerned.
@@ -735,7 +731,7 @@ HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
* on the insertion without aborting the whole transaction, the associated
* token is also returned in snapshot->speculativeToken.
*/
-bool
+static bool
HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
Buffer buffer)
{
@@ -934,14 +930,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
* HeapTupleSatisfiesMVCC
* True iff heap tuple is valid for the given MVCC snapshot.
*
- * Here, we consider the effects of:
- * all transactions committed as of the time of the given snapshot
- * previous commands of this transaction
- *
- * Does _not_ include:
- * transactions shown as in-progress by the snapshot
- * transactions started after the snapshot was taken
- * changes made by the current command
+ * See SNAPSHOT_MVCC's definition for the intended behaviour.
*
* Notice that here, we will not update the tuple status hint bits if the
* inserting/deleting transaction is still running according to our snapshot,
@@ -959,7 +948,7 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
* inserting/deleting transaction was still running --- which was more cycles
* and more contention on the PGXACT array.
*/
-bool
+static bool
HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
Buffer buffer)
{
@@ -1390,11 +1379,13 @@ HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
* True if tuple might be visible to some transaction; false if it's
* surely dead to everyone, ie, vacuumable.
*
- * This is an interface to HeapTupleSatisfiesVacuum that meets the
- * SnapshotSatisfiesFunc API, so it can be used through a Snapshot.
+ * See SNAPSHOT_TOAST's definition for the intended behaviour.
+ *
+ * This is an interface to HeapTupleSatisfiesVacuum that's callable via
+ * HeapTupleSatisfiesSnapshot, so it can be used through a Snapshot.
* snapshot->xmin must have been set up with the xmin horizon to use.
*/
-bool
+static bool
HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot,
Buffer buffer)
{
@@ -1659,7 +1650,7 @@ TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
* dangerous to do so as the semantics of doing so during timetravel are more
* complicated than when dealing "only" with the present.
*/
-bool
+static bool
HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
Buffer buffer)
{
@@ -1796,3 +1787,44 @@ HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
else
return true;
}
+
+/*
+ * HeapTupleSatisfiesVisibility
+ * True iff heap tuple satisfies a time qual.
+ *
+ * Notes:
+ * Assumes heap tuple is valid, and buffer at least share locked.
+ *
+ * Hint bits in the HeapTuple's t_infomask may be updated as a side effect;
+ * if so, the indicated buffer is marked dirty.
+ */
+bool
+HeapTupleSatisfiesVisibility(HeapTuple tup, Snapshot snapshot, Buffer buffer)
+{
+ switch (snapshot->snapshot_type)
+ {
+ case SNAPSHOT_MVCC:
+ return HeapTupleSatisfiesMVCC(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_SELF:
+ return HeapTupleSatisfiesSelf(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_ANY:
+ return HeapTupleSatisfiesAny(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_TOAST:
+ return HeapTupleSatisfiesToast(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_DIRTY:
+ return HeapTupleSatisfiesDirty(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_HISTORIC_MVCC:
+ return HeapTupleSatisfiesHistoricMVCC(tup, snapshot, buffer);
+ break;
+ case SNAPSHOT_NON_VACUUMABLE:
+ return HeapTupleSatisfiesNonVacuumable(tup, snapshot, buffer);
+ break;
+ }
+
+ return false; /* keep compiler quiet */
+}
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index f61794c016a..c5826f691de 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -20,7 +20,6 @@
#include "storage/relfilenode.h"
#include "utils/relcache.h"
#include "utils/snapmgr.h"
-#include "utils/tqual.h"
typedef void *Block;
@@ -268,8 +267,8 @@ TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
if (old_snapshot_threshold >= 0
&& (snapshot) != NULL
- && ((snapshot)->satisfies == HeapTupleSatisfiesMVCC
- || (snapshot)->satisfies == HeapTupleSatisfiesToast)
+ && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
+ || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
&& !XLogRecPtrIsInvalid((snapshot)->lsn)
&& PageGetLSN(page) > (snapshot)->lsn)
TestForOldSnapshot_impl(snapshot, relation);
diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h
index 17c57b9edb7..952307103fc 100644
--- a/src/include/utils/snapshot.h
+++ b/src/include/utils/snapshot.h
@@ -20,20 +20,90 @@
#include "storage/buf.h"
+/*
+ * The different snapshot types. We use SnapshotData structures to represent
+ * both "regular" (MVCC) snapshots and "special" snapshots that have non-MVCC
+ * semantics. The specific semantics of a snapshot are encoded by its type.
+ *
+ * The behaviour of each type of snapshot should be documented alongside its
+ * enum value, best in terms that are not specific to an individual table AM.
+ *
+ * The reason the snapshot type rather than a callback as it used to be is
+ * that that allows to use the same snapshot for different table AMs without
+ * having one callback per AM.
+ */
+typedef enum SnapshotType
+{
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid for the given MVCC snapshot.
+ *
+ * Here, we consider the effects of:
+ * - all transactions committed as of the time of the given snapshot
+ * - previous commands of this transaction
+ *
+ * Does _not_ include:
+ * - transactions shown as in-progress by the snapshot
+ * - transactions started after the snapshot was taken
+ * - changes made by the current command
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_MVCC = 0,
+
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid including effects of open
+ * transactions.
+ *
+ * Here, we consider the effects of:
+ * - all committed and in-progress transactions (as of the current instant)
+ * - previous commands of this transaction
+ * - changes made by the current command
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_SELF,
+
+ /*
+ * Any tuple is visible.
+ */
+ SNAPSHOT_ANY,
+
+ /*
+ * A tuple is visible iff the tuple tuple is valid as a TOAST row.
+ */
+ SNAPSHOT_TOAST,
+
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid including effects of open
+ * transactions.
+ *
+ * Here, we consider the effects of:
+ * - all committed and in-progress transactions (as of the current instant)
+ * - previous commands of this transaction
+ * - changes made by the current command
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_DIRTY,
+
+ /*
+ * A tuple is visible iff it follows the rules of SNAPSHOT_MVCC, but
+ * supports being called in timetravel context (for decoding catalog
+ * contents in the context of logical decoding).
+ */
+ SNAPSHOT_HISTORIC_MVCC,
+
+ /*
+ * A tuple is visible iff the tuple might be visible to some transaction;
+ * false if it's surely dead to everyone, ie, vacuumable.
+ *
+ * Snapshot.xmin must have been set up with the xmin horizon to use.
+ */
+ SNAPSHOT_NON_VACUUMABLE
+} SnapshotType;
+
typedef struct SnapshotData *Snapshot;
#define InvalidSnapshot ((Snapshot) NULL)
/*
- * We use SnapshotData structures to represent both "regular" (MVCC)
- * snapshots and "special" snapshots that have non-MVCC semantics.
- * The specific semantics of a snapshot are encoded by the "satisfies"
- * function.
- */
-typedef bool (*SnapshotSatisfiesFunc) (HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-
-/*
* Struct representing all kind of possible snapshots.
*
* There are several different kinds of snapshots:
@@ -52,7 +122,7 @@ typedef bool (*SnapshotSatisfiesFunc) (HeapTuple htup,
*/
typedef struct SnapshotData
{
- SnapshotSatisfiesFunc satisfies; /* tuple test function */
+ SnapshotType snapshot_type; /* type of snapshot */
/*
* The remaining fields are used only for MVCC snapshots, and are normally
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index e3c66fe113c..049a723a69a 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -28,21 +28,11 @@ extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
/* This macro encodes the knowledge of which snapshots are MVCC-safe */
#define IsMVCCSnapshot(snapshot) \
- ((snapshot)->satisfies == HeapTupleSatisfiesMVCC || \
- (snapshot)->satisfies == HeapTupleSatisfiesHistoricMVCC)
+ ((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
+ (snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
-/*
- * HeapTupleSatisfiesVisibility
- * True iff heap tuple satisfies a time qual.
- *
- * Notes:
- * Assumes heap tuple is valid.
- * Beware of multiple evaluations of snapshot argument.
- * Hint bits in the HeapTuple's t_infomask may be updated as a side effect;
- * if so, the indicated buffer is marked dirty.
- */
-#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
- ((*(snapshot)->satisfies) (tuple, snapshot, buffer))
+extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Snapshot snapshot,
+ Buffer buffer);
/* Result codes for HeapTupleSatisfiesVacuum */
typedef enum
@@ -54,22 +44,6 @@ typedef enum
HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
} HTSV_Result;
-/* These are the "satisfies" test routines for the various snapshot types */
-extern bool HeapTupleSatisfiesMVCC(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesSelf(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesAny(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesToast(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesDirty(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesNonVacuumable(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-extern bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup,
- Snapshot snapshot, Buffer buffer);
-
/* Special "satisfies" routines with different APIs */
extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup,
CommandId curcid, Buffer buffer);
@@ -100,14 +74,14 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
* local variable of type SnapshotData, and initialize it with this macro.
*/
#define InitDirtySnapshot(snapshotdata) \
- ((snapshotdata).satisfies = HeapTupleSatisfiesDirty)
+ ((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).satisfies = HeapTupleSatisfiesNonVacuumable, \
+ ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
(snapshotdata).xmin = (xmin_horizon))
/*
@@ -115,7 +89,7 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
* to set lsn and whenTaken correctly to support snapshot_too_old.
*/
#define InitToastSnapshot(snapshotdata, l, w) \
- ((snapshotdata).satisfies = HeapTupleSatisfiesToast, \
+ ((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
(snapshotdata).lsn = (l), \
(snapshotdata).whenTaken = (w))
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 9fe950b29db..84640c47a7d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2167,7 +2167,7 @@ SnapBuildOnDisk
SnapBuildState
Snapshot
SnapshotData
-SnapshotSatisfiesFunc
+SnapshotType
SockAddr
Sort
SortBy