summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorAndres Freund2019-01-22 01:03:15 +0000
committerAndres Freund2019-01-22 01:03:15 +0000
commit63746189b23815415cacc715fdc4f6b991f1a5e7 (patch)
tree7211c6834820f094a41744e60ef73deaae8f6548 /src/include
parent8f9e934ab746907abbeeed06a1a9b995e5b4d339 (diff)
Change snapshot type to be determined by enum rather than callback.
This is in preparation for allowing the same snapshot be used for different table AMs. With the current callback based approach we would need one callback for each supported AM, which clearly would not be extensible. Thus add a new Snapshot->snapshot_type field, and move the dispatch into HeapTupleSatisfiesVisibility() (which is now a function). Later work will then dispatch calls to HeapTupleSatisfiesVisibility() and other AMs visibility functions depending on the type of the table. The central SnapshotType enum also seems like a good location to centralize documentation about the intended behaviour of various types of snapshots. As tqual.h isn't included by bufmgr.h any more (as HeapTupleSatisfies* isn't referenced by TestForOldSnapshot() anymore) a few files now need to include it directly. Author: Andres Freund, loosely based on earlier work by Haribabu Kommi Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql
Diffstat (limited to 'src/include')
-rw-r--r--src/include/storage/bufmgr.h5
-rw-r--r--src/include/utils/snapshot.h90
-rw-r--r--src/include/utils/tqual.h40
3 files changed, 89 insertions, 46 deletions
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))