@@ -2640,6 +2640,32 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
26402640 return allindexes ;
26412641}
26422642
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+
26432669/*
26442670 * lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy
26452671 *
@@ -2660,11 +2686,11 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
26602686static void
26612687lazy_vacuum_heap_rel (LVRelState * vacrel )
26622688{
2689+ ReadStream * stream ;
26632690 BlockNumber vacuumed_pages = 0 ;
26642691 Buffer vmbuffer = InvalidBuffer ;
26652692 LVSavedErrInfo saved_err_info ;
26662693 TidStoreIter * iter ;
2667- TidStoreIterResult * iter_result ;
26682694
26692695 Assert (vacrel -> do_index_vacuuming );
26702696 Assert (vacrel -> do_index_cleanup );
@@ -2680,20 +2706,37 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
26802706 InvalidBlockNumber , InvalidOffsetNumber );
26812707
26822708 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)
26842720 {
26852721 BlockNumber blkno ;
26862722 Buffer buf ;
26872723 Page page ;
2724+ TidStoreIterResult * iter_result ;
26882725 Size freespace ;
26892726 OffsetNumber offsets [MaxOffsetNumber ];
26902727 int num_offsets ;
26912728
26922729 vacuum_delay_point (false);
26932730
2694- blkno = iter_result -> blkno ;
2695- vacrel -> blkno = blkno ;
2731+ buf = read_stream_next_buffer (stream , (void * * ) & iter_result );
26962732
2733+ /* The relation is exhausted */
2734+ if (!BufferIsValid (buf ))
2735+ break ;
2736+
2737+ vacrel -> blkno = blkno = BufferGetBlockNumber (buf );
2738+
2739+ Assert (iter_result );
26972740 num_offsets = TidStoreGetBlockOffsets (iter_result , offsets , lengthof (offsets ));
26982741 Assert (num_offsets <= lengthof (offsets ));
26992742
@@ -2705,8 +2748,6 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
27052748 visibilitymap_pin (vacrel -> rel , blkno , & vmbuffer );
27062749
27072750 /* 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 );
27102751 LockBuffer (buf , BUFFER_LOCK_EXCLUSIVE );
27112752 lazy_vacuum_heap_page (vacrel , blkno , buf , offsets ,
27122753 num_offsets , vmbuffer );
@@ -2719,6 +2760,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
27192760 RecordPageWithFreeSpace (vacrel -> rel , blkno , freespace );
27202761 vacuumed_pages ++ ;
27212762 }
2763+
2764+ read_stream_end (stream );
27222765 TidStoreEndIterate (iter );
27232766
27242767 vacrel -> blkno = InvalidBlockNumber ;
0 commit comments