return allindexes;
}
+/*
+ * Read stream callback for vacuum's third phase (second pass over the heap).
+ * Gets the next block from the TID store and returns it or InvalidBlockNumber
+ * if there are no further blocks to vacuum.
+ */
+static BlockNumber
+vacuum_reap_lp_read_stream_next(ReadStream *stream,
+ void *callback_private_data,
+ void *per_buffer_data)
+{
+ TidStoreIter *iter = callback_private_data;
+ TidStoreIterResult *iter_result;
+
+ iter_result = TidStoreIterateNext(iter);
+ if (iter_result == NULL)
+ return InvalidBlockNumber;
+
+ /*
+ * Save the TidStoreIterResult for later, so we can extract the offsets.
+ * It is safe to copy the result, according to TidStoreIterateNext().
+ */
+ memcpy(per_buffer_data, iter_result, sizeof(*iter_result));
+
+ return iter_result->blkno;
+}
+
/*
* lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy
*
static void
lazy_vacuum_heap_rel(LVRelState *vacrel)
{
+ ReadStream *stream;
BlockNumber vacuumed_pages = 0;
Buffer vmbuffer = InvalidBuffer;
LVSavedErrInfo saved_err_info;
TidStoreIter *iter;
- TidStoreIterResult *iter_result;
Assert(vacrel->do_index_vacuuming);
Assert(vacrel->do_index_cleanup);
InvalidBlockNumber, InvalidOffsetNumber);
iter = TidStoreBeginIterate(vacrel->dead_items);
- while ((iter_result = TidStoreIterateNext(iter)) != NULL)
+
+ /* Set up the read stream for vacuum's second pass through the heap */
+ stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE,
+ vacrel->bstrategy,
+ vacrel->rel,
+ MAIN_FORKNUM,
+ vacuum_reap_lp_read_stream_next,
+ iter,
+ sizeof(TidStoreIterResult));
+
+ while (true)
{
BlockNumber blkno;
Buffer buf;
Page page;
+ TidStoreIterResult *iter_result;
Size freespace;
OffsetNumber offsets[MaxOffsetNumber];
int num_offsets;
vacuum_delay_point(false);
- blkno = iter_result->blkno;
- vacrel->blkno = blkno;
+ buf = read_stream_next_buffer(stream, (void **) &iter_result);
+ /* The relation is exhausted */
+ if (!BufferIsValid(buf))
+ break;
+
+ vacrel->blkno = blkno = BufferGetBlockNumber(buf);
+
+ Assert(iter_result);
num_offsets = TidStoreGetBlockOffsets(iter_result, offsets, lengthof(offsets));
Assert(num_offsets <= lengthof(offsets));
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
/* We need a non-cleanup exclusive lock to mark dead_items unused */
- buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
- vacrel->bstrategy);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
lazy_vacuum_heap_page(vacrel, blkno, buf, offsets,
num_offsets, vmbuffer);
RecordPageWithFreeSpace(vacrel->rel, blkno, freespace);
vacuumed_pages++;
}
+
+ read_stream_end(stream);
TidStoreEndIterate(iter);
vacrel->blkno = InvalidBlockNumber;