From 4a630aeb27f42a1be6b3d34007c3e5749373f09c Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Thu, 24 Oct 2024 13:53:39 +0300
Subject: [PATCH v9 4/4] Use read_stream in SP-GiST vacuum

---
 src/backend/access/spgist/spgvacuum.c | 38 ++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index eeddacd0d52..f0d8428d909 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -25,6 +25,7 @@
 #include "storage/bufmgr.h"
 #include "storage/indexfsm.h"
 #include "storage/lmgr.h"
+#include "storage/read_stream.h"
 #include "utils/snapmgr.h"
 
 
@@ -618,17 +619,15 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer)
  * Process one page during a bulkdelete scan
  */
 static void
-spgvacuumpage(spgBulkDeleteState *bds, BlockNumber blkno)
+spgvacuumpage(spgBulkDeleteState *bds, Buffer		buffer)
 {
 	Relation	index = bds->info->index;
-	Buffer		buffer;
+	BlockNumber blkno = BufferGetBlockNumber(buffer);
 	Page		page;
 
 	/* call vacuum_delay_point while not holding any buffer lock */
 	vacuum_delay_point(false);
 
-	buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno,
-								RBM_NORMAL, bds->info->strategy);
 	LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 	page = (Page) BufferGetPage(buffer);
 
@@ -805,8 +804,10 @@ spgvacuumscan(spgBulkDeleteState *bds)
 {
 	Relation	index = bds->info->index;
 	bool		needLock;
-	BlockNumber num_pages,
-				blkno;
+	BlockNumber num_pages;
+	Buffer		buf;
+	BlockRangeReadStreamPrivate p;
+	ReadStream *stream = NULL;
 
 	/* Finish setting up spgBulkDeleteState */
 	initSpGistState(&bds->spgstate, index);
@@ -833,7 +834,14 @@ spgvacuumscan(spgBulkDeleteState *bds)
 	 * delete some deletable tuples.  See more extensive comments about this
 	 * in btvacuumscan().
 	 */
-	blkno = SPGIST_METAPAGE_BLKNO + 1;
+	p.current_blocknum = SPGIST_METAPAGE_BLKNO + 1;
+	stream = read_stream_begin_relation(READ_STREAM_FULL,
+										bds->info->strategy,
+										index,
+										MAIN_FORKNUM,
+										block_range_read_stream_cb,
+										&p,
+										0);
 	for (;;)
 	{
 		/* Get the current relation length */
@@ -844,17 +852,27 @@ spgvacuumscan(spgBulkDeleteState *bds)
 			UnlockRelationForExtension(index, ExclusiveLock);
 
 		/* Quit if we've scanned the whole relation */
-		if (blkno >= num_pages)
+		if (p.current_blocknum >= num_pages)
 			break;
+
+		p.last_exclusive = num_pages;
+
 		/* Iterate over pages, then loop back to recheck length */
-		for (; blkno < num_pages; blkno++)
+		while(BufferIsValid(buf = read_stream_next_buffer(stream, NULL)))
 		{
-			spgvacuumpage(bds, blkno);
+			spgvacuumpage(bds, buf);
 			/* empty the pending-list after each page */
 			if (bds->pendingList != NULL)
 				spgprocesspending(bds);
 		}
+		Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
+		/*
+		 * After reaching the end we have to reset stream to use it again.
+		 * Extra restart in case of just one iteration does not cost us much.
+		 */
+		read_stream_reset(stream);
 	}
+	read_stream_end(stream);
 
 	/* Propagate local lastUsedPages cache to metablock */
 	SpGistUpdateMetaPage(index);
-- 
2.39.5 (Apple Git-154)

