diff options
Diffstat (limited to 'src/backend/access/gist/gistvacuum.c')
-rw-r--r-- | src/backend/access/gist/gistvacuum.c | 84 |
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; } } |