aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist')
-rw-r--r--src/backend/access/gist/gistvacuum.c84
1 files changed, 61 insertions, 23 deletions
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index dd0d9d5006c..20b1bb5dbac 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -22,6 +22,7 @@
#include "miscadmin.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
+#include "storage/read_stream.h"
#include "utils/memutils.h"
/* Working state needed by gistbulkdelete */
@@ -44,8 +45,7 @@ typedef struct
static void gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback, void *callback_state);
-static void gistvacuumpage(GistVacState *vstate, BlockNumber blkno,
- BlockNumber orig_blkno);
+static void gistvacuumpage(GistVacState *vstate, Buffer buffer);
static void gistvacuum_delete_empty_pages(IndexVacuumInfo *info,
GistVacState *vstate);
static bool gistdeletepage(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
@@ -129,8 +129,9 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
GistVacState vstate;
BlockNumber num_pages;
bool needLock;
- BlockNumber blkno;
MemoryContext oldctx;
+ BlockRangeReadStreamPrivate p;
+ ReadStream *stream = NULL;
/*
* Reset fields that track information about the entire index now. This
@@ -208,7 +209,14 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
*/
needLock = !RELATION_IS_LOCAL(rel);
- blkno = GIST_ROOT_BLKNO;
+ p.current_blocknum = GIST_ROOT_BLKNO;
+ stream = read_stream_begin_relation(READ_STREAM_FULL,
+ info->strategy,
+ rel,
+ MAIN_FORKNUM,
+ block_range_read_stream_cb,
+ &p,
+ 0);
for (;;)
{
/* Get the current relation length */
@@ -219,13 +227,39 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
UnlockRelationForExtension(rel, ExclusiveLock);
/* Quit if we've scanned the whole relation */
- if (blkno >= num_pages)
+ if (p.current_blocknum >= num_pages)
break;
- /* Iterate over pages, then loop back to recheck length */
- for (; blkno < num_pages; blkno++)
- gistvacuumpage(&vstate, blkno, blkno);
+
+ p.last_exclusive = num_pages;
+
+ /* Iterate over pages, then loop back to recheck relation length */
+ while (true)
+ {
+ Buffer buf;
+
+ /* call vacuum_delay_point while not holding any buffer lock */
+ vacuum_delay_point(false);
+
+ buf = read_stream_next_buffer(stream, NULL);
+
+ if (!BufferIsValid(buf))
+ break;
+
+ gistvacuumpage(&vstate, buf);
+ }
+
+ Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
+
+ /*
+ * We have to reset the read stream to use it again. After returning
+ * InvalidBuffer, the read stream API won't invoke our callback again
+ * until the stream has been reset.
+ */
+ read_stream_reset(stream);
}
+ read_stream_end(stream);
+
/*
* If we found any recyclable pages (and recorded them in the FSM), then
* forcibly update the upper-level FSM pages to ensure that searchers can
@@ -260,34 +294,32 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
/*
* gistvacuumpage --- VACUUM one page
*
- * This processes a single page for gistbulkdelete(). In some cases we
- * must go back and re-examine previously-scanned pages; this routine
- * recurses when necessary to handle that case.
- *
- * blkno is the page to process. orig_blkno is the highest block number
- * reached by the outer gistvacuumscan loop (the same as blkno, unless we
- * are recursing to re-examine a previous page).
+ * This processes a single page for gistbulkdelete(). `buffer` contains the
+ * page to process. In some cases we must go back and reexamine
+ * previously-scanned pages; this routine recurses when necessary to handle
+ * that case.
*/
static void
-gistvacuumpage(GistVacState *vstate, BlockNumber blkno, BlockNumber orig_blkno)
+gistvacuumpage(GistVacState *vstate, Buffer buffer)
{
IndexVacuumInfo *info = vstate->info;
IndexBulkDeleteCallback callback = vstate->callback;
void *callback_state = vstate->callback_state;
Relation rel = info->index;
- Buffer buffer;
+ BlockNumber orig_blkno = BufferGetBlockNumber(buffer);
Page page;
BlockNumber recurse_to;
+ /*
+ * orig_blkno is the highest block number reached by the outer
+ * gistvacuumscan() loop. This will be the same as blkno unless we are
+ * recursing to reexamine a previous page.
+ */
+ BlockNumber blkno = orig_blkno;
+
restart:
recurse_to = InvalidBlockNumber;
- /* call vacuum_delay_point while not holding any buffer lock */
- vacuum_delay_point(false);
-
- buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
- info->strategy);
-
/*
* We are not going to stay here for a long time, aggressively grab an
* exclusive lock.
@@ -450,6 +482,12 @@ restart:
if (recurse_to != InvalidBlockNumber)
{
blkno = recurse_to;
+
+ /* check for vacuum delay while not holding any buffer lock */
+ vacuum_delay_point(false);
+
+ buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
+ info->strategy);
goto restart;
}
}