]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make heap_page_is_all_visible independent of LVRelState
authorMelanie Plageman <melanieplageman@gmail.com>
Tue, 14 Oct 2025 21:43:41 +0000 (17:43 -0400)
committerMelanie Plageman <melanieplageman@gmail.com>
Tue, 14 Oct 2025 21:43:41 +0000 (17:43 -0400)
This function only requires a few fields from LVRelState, so pass them
in individually.

This change allows calling heap_page_is_all_visible() from code such as
pruneheap.c, which does not have access to an LVRelState.

Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/2wk7jo4m4qwh5sn33pfgerdjfujebbccsmmlownybddbh6nawl%40mdyyqpqzxjek

src/backend/access/heap/vacuumlazy.c

index 6b9645e36818cc66de5191d4c1ebffd4998b2295..71fbd68c8eaeb91b8418a0a4b1154daea680d3e3 100644 (file)
@@ -463,15 +463,21 @@ static void dead_items_add(LVRelState *vacrel, BlockNumber blkno, OffsetNumber *
                                                   int num_offsets);
 static void dead_items_reset(LVRelState *vacrel);
 static void dead_items_cleanup(LVRelState *vacrel);
+
 #ifdef USE_ASSERT_CHECKING
-static bool heap_page_is_all_visible(LVRelState *vacrel, Buffer buf,
-                                                                        TransactionId *visibility_cutoff_xid, bool *all_frozen);
+static bool heap_page_is_all_visible(Relation rel, Buffer buf,
+                                                                        TransactionId OldestXmin,
+                                                                        bool *all_frozen,
+                                                                        TransactionId *visibility_cutoff_xid,
+                                                                        OffsetNumber *logging_offnum);
 #endif
-static bool heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
+static bool heap_page_would_be_all_visible(Relation rel, Buffer buf,
+                                                                                  TransactionId OldestXmin,
                                                                                   OffsetNumber *deadoffsets,
                                                                                   int ndeadoffsets,
                                                                                   bool *all_frozen,
-                                                                                  TransactionId *visibility_cutoff_xid);
+                                                                                  TransactionId *visibility_cutoff_xid,
+                                                                                  OffsetNumber *logging_offnum);
 static void update_relstats_all_indexes(LVRelState *vacrel);
 static void vacuum_error_callback(void *arg);
 static void update_vacuum_error_info(LVRelState *vacrel,
@@ -2016,8 +2022,9 @@ lazy_scan_prune(LVRelState *vacrel,
 
                Assert(presult.lpdead_items == 0);
 
-               if (!heap_page_is_all_visible(vacrel, buf,
-                                                                         &debug_cutoff, &debug_all_frozen))
+               if (!heap_page_is_all_visible(vacrel->rel, buf,
+                                                                         vacrel->cutoffs.OldestXmin, &debug_all_frozen,
+                                                                         &debug_cutoff, &vacrel->offnum))
                        Assert(false);
 
                Assert(presult.all_frozen == debug_all_frozen);
@@ -2877,9 +2884,11 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
         * visibility checks may perform I/O and allocate memory, they must be
         * done outside the critical section.
         */
-       if (heap_page_would_be_all_visible(vacrel, buffer,
+       if (heap_page_would_be_all_visible(vacrel->rel, buffer,
+                                                                          vacrel->cutoffs.OldestXmin,
                                                                           deadoffsets, num_offsets,
-                                                                          &all_frozen, &visibility_cutoff_xid))
+                                                                          &all_frozen, &visibility_cutoff_xid,
+                                                                          &vacrel->offnum))
        {
                vmflags |= VISIBILITYMAP_ALL_VISIBLE;
                if (all_frozen)
@@ -3629,15 +3638,19 @@ dead_items_cleanup(LVRelState *vacrel)
  * reason not to use it outside of asserts.
  */
 static bool
-heap_page_is_all_visible(LVRelState *vacrel, Buffer buf,
+heap_page_is_all_visible(Relation rel, Buffer buf,
+                                                TransactionId OldestXmin,
+                                                bool *all_frozen,
                                                 TransactionId *visibility_cutoff_xid,
-                                                bool *all_frozen)
+                                                OffsetNumber *logging_offnum)
 {
 
-       return heap_page_would_be_all_visible(vacrel, buf,
+       return heap_page_would_be_all_visible(rel, buf,
+                                                                                 OldestXmin,
                                                                                  NULL, 0,
                                                                                  all_frozen,
-                                                                                 visibility_cutoff_xid);
+                                                                                 visibility_cutoff_xid,
+                                                                                 logging_offnum);
 }
 #endif
 
@@ -3654,10 +3667,14 @@ heap_page_is_all_visible(LVRelState *vacrel, Buffer buf,
  * Returns true if the page is all-visible other than the provided
  * deadoffsets and false otherwise.
  *
+ * OldestXmin is used to determine visibility.
+ *
  * Output parameters:
  *
  *  - *all_frozen: true if every tuple on the page is frozen
  *  - *visibility_cutoff_xid: newest xmin; valid only if page is all-visible
+ *  - *logging_offnum: OffsetNumber of current tuple being processed;
+ *     used by vacuum's error callback system.
  *
  * Callers looking to verify that the page is already all-visible can call
  * heap_page_is_all_visible().
@@ -3668,11 +3685,13 @@ heap_page_is_all_visible(LVRelState *vacrel, Buffer buf,
  * side-effects.
  */
 static bool
-heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
+heap_page_would_be_all_visible(Relation rel, Buffer buf,
+                                                          TransactionId OldestXmin,
                                                           OffsetNumber *deadoffsets,
                                                           int ndeadoffsets,
                                                           bool *all_frozen,
-                                                          TransactionId *visibility_cutoff_xid)
+                                                          TransactionId *visibility_cutoff_xid,
+                                                          OffsetNumber *logging_offnum)
 {
        Page            page = BufferGetPage(buf);
        BlockNumber blockno = BufferGetBlockNumber(buf);
@@ -3707,7 +3726,7 @@ heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
                 * Set the offset number so that we can display it along with any
                 * error that occurred while processing this tuple.
                 */
-               vacrel->offnum = offnum;
+               *logging_offnum = offnum;
                itemid = PageGetItemId(page, offnum);
 
                /* Unused or redirect line pointers are of no interest */
@@ -3737,13 +3756,11 @@ heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
 
                tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
                tuple.t_len = ItemIdGetLength(itemid);
-               tuple.t_tableOid = RelationGetRelid(vacrel->rel);
+               tuple.t_tableOid = RelationGetRelid(rel);
 
                /* Visibility checks may do IO or allocate memory */
                Assert(CritSectionCount == 0);
-
-               switch (HeapTupleSatisfiesVacuum(&tuple, vacrel->cutoffs.OldestXmin,
-                                                                                buf))
+               switch (HeapTupleSatisfiesVacuum(&tuple, OldestXmin, buf))
                {
                        case HEAPTUPLE_LIVE:
                                {
@@ -3762,8 +3779,7 @@ heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
                                         * that everyone sees it as committed?
                                         */
                                        xmin = HeapTupleHeaderGetXmin(tuple.t_data);
-                                       if (!TransactionIdPrecedes(xmin,
-                                                                                          vacrel->cutoffs.OldestXmin))
+                                       if (!TransactionIdPrecedes(xmin, OldestXmin))
                                        {
                                                all_visible = false;
                                                *all_frozen = false;
@@ -3798,7 +3814,7 @@ heap_page_would_be_all_visible(LVRelState *vacrel, Buffer buf,
        }                                                       /* scan along page */
 
        /* Clear the offset information once we have processed the given page. */
-       vacrel->offnum = InvalidOffsetNumber;
+       *logging_offnum = InvalidOffsetNumber;
 
        return all_visible;
 }