diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index 827312306f60..be031a1795e9 100644 --- a/contrib/amcheck/verify_heapam.c +++ b/contrib/amcheck/verify_heapam.c @@ -25,6 +25,7 @@ #include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/procarray.h" +#include "storage/read_stream.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/rel.h" @@ -185,6 +186,43 @@ static XidBoundsViolation get_xid_status(TransactionId xid, HeapCheckContext *ctx, XidCommitStatus *status); +typedef struct heapamcheck_rs_perblock_data +{ + BlockRangeReadStreamPrivate range; + SkipPages skip_option; + Relation rel; + Buffer *vmbuffer; +} heapamcheck_rs_perblock_data; + +static BlockNumber +heapam_read_stream_next_block(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) +{ + heapamcheck_rs_perblock_data *p = callback_private_data; + + for (BlockNumber i; (i = p->range.current_blocknum++) < p->range.last_exclusive;) + { + int32 mapbits = visibilitymap_get_status(p->rel, i, p->vmbuffer); + + if (p->skip_option == SKIP_PAGES_ALL_FROZEN) + { + if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0) + continue; + } + + if (p->skip_option == SKIP_PAGES_ALL_VISIBLE) + { + if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0) + continue; + } + + return i; + } + + return InvalidBlockNumber; +} + /* * Scan and report corruption in heap pages, optionally reconciling toasted * attributes with entries in the associated toast table. Intended to be @@ -231,6 +269,11 @@ verify_heapam(PG_FUNCTION_ARGS) BlockNumber last_block; BlockNumber nblocks; const char *skip; + ReadStream *stream; + int read_stream_flags; + ReadStreamBlockNumberCB cb; + heapamcheck_rs_perblock_data rsdata; + void *stream_callback_private; /* Check supplied arguments */ if (PG_ARGISNULL(0)) @@ -404,7 +447,34 @@ verify_heapam(PG_FUNCTION_ARGS) if (TransactionIdIsNormal(ctx.relfrozenxid)) ctx.oldest_xid = ctx.relfrozenxid; - for (ctx.blkno = first_block; ctx.blkno <= last_block; ctx.blkno++) + rsdata.range.current_blocknum = first_block; + rsdata.range.last_exclusive = last_block + 1; + rsdata.skip_option = skip_option; + rsdata.rel = ctx.rel; + rsdata.vmbuffer = &vmbuffer; + + if (skip_option == SKIP_PAGES_NONE) + { + cb = block_range_read_stream_cb; + read_stream_flags = READ_STREAM_SEQUENTIAL | READ_STREAM_FULL; + stream_callback_private = &rsdata.range; + } + else + { + cb = heapam_read_stream_next_block; + read_stream_flags = READ_STREAM_DEFAULT; + stream_callback_private = &rsdata; + } + + stream = read_stream_begin_relation(read_stream_flags, + ctx.bstrategy, + ctx.rel, + MAIN_FORKNUM, + cb, + stream_callback_private, + 0); + + while ((ctx.buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) { OffsetNumber maxoff; OffsetNumber predecessor[MaxOffsetNumber]; @@ -417,30 +487,11 @@ verify_heapam(PG_FUNCTION_ARGS) memset(predecessor, 0, sizeof(OffsetNumber) * MaxOffsetNumber); - /* Optionally skip over all-frozen or all-visible blocks */ - if (skip_option != SKIP_PAGES_NONE) - { - int32 mapbits; - - mapbits = (int32) visibilitymap_get_status(ctx.rel, ctx.blkno, - &vmbuffer); - if (skip_option == SKIP_PAGES_ALL_FROZEN) - { - if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0) - continue; - } - - if (skip_option == SKIP_PAGES_ALL_VISIBLE) - { - if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0) - continue; - } - } - - /* Read and lock the next page. */ - ctx.buffer = ReadBufferExtended(ctx.rel, MAIN_FORKNUM, ctx.blkno, - RBM_NORMAL, ctx.bstrategy); + /* Lock the next page. */ + Assert(BufferIsValid(ctx.buffer)); LockBuffer(ctx.buffer, BUFFER_LOCK_SHARE); + + ctx.blkno = BufferGetBlockNumber(ctx.buffer); ctx.page = BufferGetPage(ctx.buffer); /* Perform tuple checks */ @@ -798,6 +849,9 @@ verify_heapam(PG_FUNCTION_ARGS) if (on_error_stop && ctx.is_corrupt) break; } + /* Ensure that the stream is completely read */ + Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer); + read_stream_end(stream); if (vmbuffer != InvalidBuffer) ReleaseBuffer(vmbuffer); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 9442a4841aa3..b5047ebd5940 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3626,6 +3626,7 @@ gtrgm_consistent_cache gzFile hashfunc hbaPort +heapamcheck_rs_perblock_data heap_page_items_state help_handler hlCheck