@@ -2640,6 +2640,32 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
2640
2640
return allindexes ;
2641
2641
}
2642
2642
2643
+ /*
2644
+ * Read stream callback for vacuum's third phase (second pass over the heap).
2645
+ * Gets the next block from the TID store and returns it or InvalidBlockNumber
2646
+ * if there are no further blocks to vacuum.
2647
+ */
2648
+ static BlockNumber
2649
+ vacuum_reap_lp_read_stream_next (ReadStream * stream ,
2650
+ void * callback_private_data ,
2651
+ void * per_buffer_data )
2652
+ {
2653
+ TidStoreIter * iter = callback_private_data ;
2654
+ TidStoreIterResult * iter_result ;
2655
+
2656
+ iter_result = TidStoreIterateNext (iter );
2657
+ if (iter_result == NULL )
2658
+ return InvalidBlockNumber ;
2659
+
2660
+ /*
2661
+ * Save the TidStoreIterResult for later, so we can extract the offsets.
2662
+ * It is safe to copy the result, according to TidStoreIterateNext().
2663
+ */
2664
+ memcpy (per_buffer_data , iter_result , sizeof (* iter_result ));
2665
+
2666
+ return iter_result -> blkno ;
2667
+ }
2668
+
2643
2669
/*
2644
2670
* lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy
2645
2671
*
@@ -2660,11 +2686,11 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
2660
2686
static void
2661
2687
lazy_vacuum_heap_rel (LVRelState * vacrel )
2662
2688
{
2689
+ ReadStream * stream ;
2663
2690
BlockNumber vacuumed_pages = 0 ;
2664
2691
Buffer vmbuffer = InvalidBuffer ;
2665
2692
LVSavedErrInfo saved_err_info ;
2666
2693
TidStoreIter * iter ;
2667
- TidStoreIterResult * iter_result ;
2668
2694
2669
2695
Assert (vacrel -> do_index_vacuuming );
2670
2696
Assert (vacrel -> do_index_cleanup );
@@ -2680,20 +2706,37 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
2680
2706
InvalidBlockNumber , InvalidOffsetNumber );
2681
2707
2682
2708
iter = TidStoreBeginIterate (vacrel -> dead_items );
2683
- while ((iter_result = TidStoreIterateNext (iter )) != NULL )
2709
+
2710
+ /* Set up the read stream for vacuum's second pass through the heap */
2711
+ stream = read_stream_begin_relation (READ_STREAM_MAINTENANCE ,
2712
+ vacrel -> bstrategy ,
2713
+ vacrel -> rel ,
2714
+ MAIN_FORKNUM ,
2715
+ vacuum_reap_lp_read_stream_next ,
2716
+ iter ,
2717
+ sizeof (TidStoreIterResult ));
2718
+
2719
+ while (true)
2684
2720
{
2685
2721
BlockNumber blkno ;
2686
2722
Buffer buf ;
2687
2723
Page page ;
2724
+ TidStoreIterResult * iter_result ;
2688
2725
Size freespace ;
2689
2726
OffsetNumber offsets [MaxOffsetNumber ];
2690
2727
int num_offsets ;
2691
2728
2692
2729
vacuum_delay_point (false);
2693
2730
2694
- blkno = iter_result -> blkno ;
2695
- vacrel -> blkno = blkno ;
2731
+ buf = read_stream_next_buffer (stream , (void * * ) & iter_result );
2696
2732
2733
+ /* The relation is exhausted */
2734
+ if (!BufferIsValid (buf ))
2735
+ break ;
2736
+
2737
+ vacrel -> blkno = blkno = BufferGetBlockNumber (buf );
2738
+
2739
+ Assert (iter_result );
2697
2740
num_offsets = TidStoreGetBlockOffsets (iter_result , offsets , lengthof (offsets ));
2698
2741
Assert (num_offsets <= lengthof (offsets ));
2699
2742
@@ -2705,8 +2748,6 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
2705
2748
visibilitymap_pin (vacrel -> rel , blkno , & vmbuffer );
2706
2749
2707
2750
/* We need a non-cleanup exclusive lock to mark dead_items unused */
2708
- buf = ReadBufferExtended (vacrel -> rel , MAIN_FORKNUM , blkno , RBM_NORMAL ,
2709
- vacrel -> bstrategy );
2710
2751
LockBuffer (buf , BUFFER_LOCK_EXCLUSIVE );
2711
2752
lazy_vacuum_heap_page (vacrel , blkno , buf , offsets ,
2712
2753
num_offsets , vmbuffer );
@@ -2719,6 +2760,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
2719
2760
RecordPageWithFreeSpace (vacrel -> rel , blkno , freespace );
2720
2761
vacuumed_pages ++ ;
2721
2762
}
2763
+
2764
+ read_stream_end (stream );
2722
2765
TidStoreEndIterate (iter );
2723
2766
2724
2767
vacrel -> blkno = InvalidBlockNumber ;
0 commit comments