From 93d2790fac9c66c67165555d541410777ec9ad3b Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 20 Mar 2024 14:13:33 -0400
Subject: [PATCH 2/9] comments on 0001

---
 src/backend/access/heap/heapam.c    |  4 +-
 src/backend/access/heap/pruneheap.c |  7 ++-
 src/include/access/heapam_xlog.h    | 88 ++++++++++++++++++++---------
 3 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e6cfffd9f3e..17b733fd706 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8706,6 +8706,8 @@ heap_xlog_prune(XLogReaderState *record)
 		MarkBufferDirty(buffer);
 	}
 
+	// TODO: should we avoid this if we only froze? heap_xlog_freeze() doesn't
+	// do it
 	if (BufferIsValid(buffer))
 	{
 		Size		freespace = PageGetHeapFreeSpace(BufferGetPage(buffer));
@@ -8713,7 +8715,7 @@ heap_xlog_prune(XLogReaderState *record)
 		UnlockReleaseBuffer(buffer);
 
 		/*
-		 * After modifying records on a page, it's useful to update the FSM
+		 * After modifying tuples on a page, it's useful to update the FSM
 		 * about it, as it may cause the page become target for insertions
 		 * later even if vacuum decides not to visit it (which is possible if
 		 * gets marked all-visible.)
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 9773681868c..6fc5c22a22d 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -1294,7 +1294,8 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer,
 	int			nplans = 0;
 	xl_heap_freeze_plan plans[MaxHeapTuplesPerPage];
 	OffsetNumber frz_offsets[MaxHeapTuplesPerPage];
-	bool		do_freeze = (nfrozen > 0);
+	bool		do_freeze = (nfrozen > 0); // don't need these parantheses
+										   // actually probably just lose this variable
 
 	xlrec.flags = 0;
 
@@ -1311,8 +1312,8 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer,
 		xlrec.flags |= XLHP_HAS_CONFLICT_HORIZON;
 
 	/*
-	 * Prepare deduplicated representation for use in WAL record Destructively
-	 * sorts tuples array in-place.
+	 * Prepare deduplicated representation for use in WAL record. This
+	 * destructively sorts frozen tuples array in-place.
 	 */
 	if (do_freeze)
 		nplans = heap_log_freeze_plan(frozen, nfrozen, plans, frz_offsets);
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
index dfeb703d136..14e0e49e539 100644
--- a/src/include/access/heapam_xlog.h
+++ b/src/include/access/heapam_xlog.h
@@ -225,22 +225,32 @@ typedef struct xl_heap_update
 #define SizeOfHeapUpdate	(offsetof(xl_heap_update, new_offnum) + sizeof(OffsetNumber))
 
 /*
- * This is what we need to know about page pruning and freezing, both during
- * VACUUM and during opportunistic pruning.
+ * These structures and flags encode VACUUM pruning and freezing and on-access
+ * pruning page modifications.
  *
- * If XLPH_HAS_REDIRECTIONS, XLHP_HAS_DEAD_ITEMS, or XLHP_HAS_NOW_UNUSED is set,
- * acquires a full cleanup lock. Otherwise an ordinary exclusive lock is
- * enough. This can happen if freezing was the only modification to the page.
+ * xl_heap_prune is the main record. The XLHP_HAS_* flags indicate which
+ * "sub-records" are included and the other XLHP_* flags provide additional
+ * information about the conditions for replay.
  *
- * The data for block reference 0 contains "sub-records" depending on which
- * of the XLHP_HAS_* flags are set. See xlhp_* struct definitions below.
- * The layout is in the same order as the XLHP_* flags.
+ * The data for block reference 0 contains "sub-records" depending on which of
+ * the XLHP_HAS_* flags are set. Offset numbers are in the block reference data
+ * following each sub-record. See xlhp_* struct definitions below. The layout
+ * is in the same order as the XLHP_* flags.
  *
- * OFFSET NUMBERS are in the block reference 0
- *
- * If only unused item offsets are included because the record is constructed
- * during vacuum's second pass (marking LP_DEAD items LP_UNUSED) then only an
- * ordinary exclusive lock is required to replay.
+ * An example record with every sub-record included.
+ *-----------------------------------------------------------------------------
+ * uint8 		       flags (begin xl_heap_prune)
+ * TransactionId       snapshot_conflict_horizon
+ * uint16		       nplans (begin xlhp_freeze)
+ * xl_heap_freeze_plan plans[nplans]
+ * uint16			   nredirected (begin xlhp_prune_items)
+ * OffsetNumber		   redirected[2 * nredirected]
+ * uint16			   ndead (begin xlhp_prune_items)
+ * OffsetNumber		   nowdead[ndead]
+ * uint16			   nunused (begin xlhp_prune_items)
+ * OffsetNumber		   nowunused[nunused]
+ * OffsetNumber		   frz_offsets[sum([plan.ntuples for plan in plans])]
+ *-----------------------------------------------------------------------------
  */
 typedef struct xl_heap_prune
 {
@@ -251,20 +261,42 @@ typedef struct xl_heap_prune
 #define		XLHP_IS_CATALOG_REL			(1 << 1)
 
 /*
- * During vacuum's second pass which sets LP_DEAD items LP_UNUSED, we will only
- * truncate the line pointer array, not call PageRepairFragmentation. We need
- * this flag to differentiate what kind of lock (exclusive or cleanup) to take
- * on the buffer and whether to call PageTruncateLinePointerArray() or
- * PageRepairFragementation().
+ * Vacuum's second pass sets LP_DEAD items LP_UNUSED and truncates the line
+ * pointer array with PageTruncateLinePointerArray(). It will emit a WAL
+ * record with XLHP_LP_TRUNCATE_ONLY set to indicate that only an ordinary
+ * exclusive lock is needed to replay the record. When XLHP_LP_TRUNCATE_ONLY is
+ * unset, we take a cleanup lock and call PageRepairFragementation().
  */
 #define		XLHP_LP_TRUNCATE_ONLY       (1 << 2)
 
 /*
  * Vacuum's first pass and on-access pruning may need to include a snapshot
- * conflict horizon.
+ * conflict horizon. The snapshot conflict horizon is needed regardless of
+ * whether or not a full-page image was emitted, so the
+ * snapshot_conflict_horizon is located in the "main chunk" of the WAL record,
+ * available at replay with XLogRecGetData(), while all of the sub-records are
+ * located in the block reference data, available at replay with
+ * XLogRecGetBlockData().
  */
 #define		XLHP_HAS_CONFLICT_HORIZON   (1 << 3)
+
+/*
+ * Indicates that an xlhp_freeze sub-record and one or more xl_heap_freeze_plan
+ * sub-records are present. If XLHP_HAS_FREEZE_PLANS is set and no other page
+ * modifications will be made, an ordinary exclusive lock on the buffer is
+ * sufficient to replay the record.
+ */
 #define		XLHP_HAS_FREEZE_PLANS		(1 << 4)
+
+/*
+ * XLPH_HAS_REDIRECTIONS, XLHP_HAS_DEAD_ITEMS, and XLHP_HAS_NOW_UNUSED indicate
+ * that xlhp_prune_items sub-records with redirected, dead, and unused item
+ * offsets are present in the record. If XLHP_HAS_REDIRECTIONS or
+ * XLHP_HAS_DEAD_ITEMS is set or if XLHP_HAS_NOW_UNUSED items is set and
+ * XLHP_LP_TRUNCATE_ONLY is not set, a full cleanup lock on the buffer is
+ * needed to replay the record. Otherwise, an ordinary exclusive lock is
+ * sufficient.
+ */
 #define		XLHP_HAS_REDIRECTIONS		(1 << 5)
 #define		XLHP_HAS_DEAD_ITEMS	        (1 << 6)
 #define		XLHP_HAS_NOW_UNUSED_ITEMS   (1 << 7)
@@ -299,15 +331,16 @@ typedef struct xl_heap_freeze_plan
 } xl_heap_freeze_plan;
 
 /*
- * As of Postgres 17, XLOG_HEAP2_PRUNE records replace
- * XLOG_HEAP2_FREEZE_PAGE records.
+ * As of Postgres 17, XLOG_HEAP2_PRUNE records replace XLOG_HEAP2_FREEZE_PAGE
+ * records.
  *
  * This is what we need to know about a block being frozen during vacuum
  *
- * Backup block 0's data contains an array of xl_heap_freeze_plan structs
- * (with nplans elements), followed by one or more page offset number arrays.
- * Each such page offset number array corresponds to a single freeze plan
- * (REDO routine freezes corresponding heap tuples using freeze plan).
+ * The backup block's data contains an array of xl_heap_freeze_plan structs
+ * (with nplans elements). The individual item offsets are located in an array
+ * at the end of the entire record with with nplans * (each plan's ntuples)
+ * members. Those offsets are in the same order as the plans. The REDO routine
+ * uses the offsets to freeze the corresponding heap tuples.
  */
 typedef struct xlhp_freeze
 {
@@ -316,8 +349,9 @@ typedef struct xlhp_freeze
 } xlhp_freeze;
 
 /*
- * Sub-record type contained in block reference 0 of a prune record if
- * XLHP_HAS_REDIRECTIONS/XLHP_HAS_DEAD_ITEMS/XLHP_HAS_NOW_UNUSED_ITEMS is set.
+ * Generic sub-record type contained in block reference 0 of an xl_heap_prune
+ * record and used for redirect, dead, and unused items if any of
+ * XLHP_HAS_REDIRECTIONS/XLHP_HAS_DEAD_ITEMS/XLHP_HAS_NOW_UNUSED_ITEMS are set.
  * Note that in the XLHP_HAS_REDIRECTIONS variant, there are actually 2 *
  * length number of OffsetNumbers in the data.
  */
-- 
2.40.1

