public inbox for [email protected]help / color / mirror / Atom feed
[PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface 7+ messages / 2 participants [nested] [flat]
* [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_get_next_block(). --- src/backend/access/heap/vacuumlazy.c | 79 +++++++++++++++++++++------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 65d257aab83..fbbc87938e4 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -189,6 +195,12 @@ typedef struct LVRelState BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ + /* + * The most recent block submitted in the streaming read callback by the + * first vacuum pass. + */ + BlockNumber blkno_prefetch; + /* Statistics output by us, for table */ double new_rel_tuples; /* new estimated total # of tuples */ double new_live_tuples; /* new estimated total # of live tuples */ @@ -232,7 +244,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, @@ -416,6 +428,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->nonempty_pages = 0; /* dead_items_alloc allocates vacrel->dead_items later on */ + /* relies on InvalidBlockNumber overflowing to 0 */ + vacrel->blkno_prefetch = InvalidBlockNumber; + /* Allocate/initialize output statistics state */ vacrel->new_rel_tuples = 0; vacrel->new_live_tuples = 0; @@ -776,6 +791,22 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + vacrel->blkno_prefetch++; + + heap_vac_scan_get_next_block(vacrel, + vacrel->blkno_prefetch, &vacrel->blkno_prefetch, + all_visible_according_to_vm); + + return vacrel->blkno_prefetch; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -815,12 +846,11 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; - /* relies on InvalidBlockNumber overflowing to 0 */ - BlockNumber blkno = InvalidBlockNumber; VacDeadItems *dead_items = vacrel->dead_items; const int initprog_index[] = { PROGRESS_VACUUM_PHASE, @@ -828,6 +858,11 @@ lazy_scan_heap(LVRelState *vacrel) PROGRESS_VACUUM_MAX_DEAD_TUPLES }; int64 initprog_val[3]; + PgStreamingRead *pgsr; + + pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, vacuum_scan_pgsr_next); /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; @@ -838,13 +873,19 @@ lazy_scan_heap(LVRelState *vacrel) vacrel->skip.next_unskippable_block = InvalidBlockNumber; vacrel->skip.vmbuffer = InvalidBuffer; - while (heap_vac_scan_get_next_block(vacrel, blkno + 1, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = + pg_streaming_read_buffer_get_next(pgsr, (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -912,9 +953,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vacrel->skip.vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -970,7 +1008,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - all_visible_according_to_vm, + *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1027,7 +1065,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1042,6 +1080,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1053,11 +1093,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1090,7 +1130,7 @@ lazy_scan_heap(LVRelState *vacrel) * * The block number and visibility status of the next block to process are set * in blkno and all_visible_according_to_vm. heap_vac_scan_get_next_block() - * returns false if there are no further blocks to process. + * sets blkno to InvalidBlockNumber if there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read and vacrel->skippedallvis is set to ensure we don't @@ -1110,7 +1150,7 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm) { @@ -1119,7 +1159,7 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, if (next_block >= vacrel->rel_pages) { *blkno = InvalidBlockNumber; - return false; + return; } if (vacrel->skip.next_unskippable_block == InvalidBlockNumber || @@ -1214,7 +1254,6 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, *all_visible_according_to_vm = true; *blkno = next_block; - return true; } /* -- 2.40.1 --lb5e4aqx4b6ik5lq Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v5a-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_get_next_block(). --- src/backend/access/heap/vacuumlazy.c | 79 +++++++++++++++++++++------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 65d257aab83..fbbc87938e4 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -189,6 +195,12 @@ typedef struct LVRelState BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ + /* + * The most recent block submitted in the streaming read callback by the + * first vacuum pass. + */ + BlockNumber blkno_prefetch; + /* Statistics output by us, for table */ double new_rel_tuples; /* new estimated total # of tuples */ double new_live_tuples; /* new estimated total # of live tuples */ @@ -232,7 +244,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, @@ -416,6 +428,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->nonempty_pages = 0; /* dead_items_alloc allocates vacrel->dead_items later on */ + /* relies on InvalidBlockNumber overflowing to 0 */ + vacrel->blkno_prefetch = InvalidBlockNumber; + /* Allocate/initialize output statistics state */ vacrel->new_rel_tuples = 0; vacrel->new_live_tuples = 0; @@ -776,6 +791,22 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + vacrel->blkno_prefetch++; + + heap_vac_scan_get_next_block(vacrel, + vacrel->blkno_prefetch, &vacrel->blkno_prefetch, + all_visible_according_to_vm); + + return vacrel->blkno_prefetch; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -815,12 +846,11 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; - /* relies on InvalidBlockNumber overflowing to 0 */ - BlockNumber blkno = InvalidBlockNumber; VacDeadItems *dead_items = vacrel->dead_items; const int initprog_index[] = { PROGRESS_VACUUM_PHASE, @@ -828,6 +858,11 @@ lazy_scan_heap(LVRelState *vacrel) PROGRESS_VACUUM_MAX_DEAD_TUPLES }; int64 initprog_val[3]; + PgStreamingRead *pgsr; + + pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, vacuum_scan_pgsr_next); /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; @@ -838,13 +873,19 @@ lazy_scan_heap(LVRelState *vacrel) vacrel->skip.next_unskippable_block = InvalidBlockNumber; vacrel->skip.vmbuffer = InvalidBuffer; - while (heap_vac_scan_get_next_block(vacrel, blkno + 1, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = + pg_streaming_read_buffer_get_next(pgsr, (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -912,9 +953,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vacrel->skip.vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -970,7 +1008,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - all_visible_according_to_vm, + *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1027,7 +1065,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1042,6 +1080,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1053,11 +1093,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1090,7 +1130,7 @@ lazy_scan_heap(LVRelState *vacrel) * * The block number and visibility status of the next block to process are set * in blkno and all_visible_according_to_vm. heap_vac_scan_get_next_block() - * returns false if there are no further blocks to process. + * sets blkno to InvalidBlockNumber if there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read and vacrel->skippedallvis is set to ensure we don't @@ -1110,7 +1150,7 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm) { @@ -1119,7 +1159,7 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, if (next_block >= vacrel->rel_pages) { *blkno = InvalidBlockNumber; - return false; + return; } if (vacrel->skip.next_unskippable_block == InvalidBlockNumber || @@ -1214,7 +1254,6 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, *all_visible_according_to_vm = true; *blkno = next_block; - return true; } /* -- 2.40.1 --lb5e4aqx4b6ik5lq Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v5a-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_next_block(). --- src/backend/access/heap/vacuumlazy.c | 131 +++++++++++++++++++-------- 1 file changed, 92 insertions(+), 39 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index d2c8f27fc57..d07a2a58b15 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -220,6 +226,12 @@ typedef struct LVRelState BlockNumber next_unskippable_block; /* Next unskippable block's visibility status */ bool next_unskippable_allvis; + + /* + * Buffer containing block of VM with visibility information for + * next_unskippable_block. + */ + Buffer next_unskippable_vmbuffer; } next_block_state; } LVRelState; @@ -233,8 +245,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, +static void heap_vac_scan_next_block(LVRelState *vacrel, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, @@ -777,6 +788,47 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + heap_vac_scan_next_block(vacrel, + all_visible_according_to_vm); + + /* + * If there are no further blocks to vacuum in the relation, release the + * vmbuffer. + */ + if (!BlockNumberIsValid(vacrel->next_block_state.current_block) && + BufferIsValid(vacrel->next_block_state.next_unskippable_vmbuffer)) + { + ReleaseBuffer(vacrel->next_block_state.next_unskippable_vmbuffer); + vacrel->next_block_state.next_unskippable_vmbuffer = InvalidBuffer; + } + + return vacrel->next_block_state.current_block; +} + +static inline PgStreamingRead * +vac_scan_pgsr_alloc(LVRelState *vacrel, PgStreamingReadBufferCB next_block_cb) +{ + PgStreamingRead *result = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, next_block_cb); + + /* + * Initialize for first heap_vac_scan_next_block() call. These rely on + * InvalidBlockNumber + 1 = 0 + */ + vacrel->next_block_state.current_block = InvalidBlockNumber; + vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; + + return result; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -816,10 +868,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, - blkno, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; VacDeadItems *dead_items = vacrel->dead_items; Buffer vmbuffer = InvalidBuffer; @@ -830,23 +882,27 @@ lazy_scan_heap(LVRelState *vacrel) }; int64 initprog_val[3]; + PgStreamingRead *pgsr = vac_scan_pgsr_alloc(vacrel, vacuum_scan_pgsr_next); + /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; initprog_val[1] = rel_pages; initprog_val[2] = dead_items->max_items; pgstat_progress_update_multi_param(3, initprog_index, initprog_val); - /* Initialize for first heap_vac_scan_next_block() call */ - vacrel->next_block_state.current_block = InvalidBlockNumber; - vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; - - while (heap_vac_scan_next_block(vacrel, &vmbuffer, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = pg_streaming_read_buffer_get_next(pgsr, + (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -914,9 +970,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -973,7 +1026,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - vmbuffer, all_visible_according_to_vm, + vmbuffer, *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1030,7 +1083,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1045,6 +1098,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1056,11 +1111,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1072,12 +1127,13 @@ lazy_scan_heap(LVRelState *vacrel) * * lazy_scan_heap() calls here every time it needs to get the next block to * prune and vacuum, using the visibility map, vacuum options, and various - * thresholds to skip blocks which do not need to be processed and set blkno to - * the next block that actually needs to be processed. + * thresholds to skip blocks which do not need to be processed and set + * current_block to the next block that actually needs to be processed. * - * The block number and visibility status of the next block to process are set - * in blkno and all_visible_according_to_vm. heap_vac_scan_next_block() - * returns false if there are no further blocks to process. + * The number and visibility status of the next block to process are set in + * vacrel->next_block_state->current_block and all_visible_according_to_vm. + * vacrel->next_block_state->current_block is set to InvalidBlockNumber if + * there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read, members of vacrel->next_block_state are read and set as @@ -1085,12 +1141,10 @@ lazy_scan_heap(LVRelState *vacrel) * don't advance relfrozenxid when we have skipped vacuuming all-visible * blocks. * - * vmbuffer is an output parameter which, upon return, will contain the block - * from the VM containing visibility information for the next unskippable heap - * block. If we decide not to skip this heap block, the caller is responsible - * for fetching the correct VM block into vmbuffer before using it. This is - * okay as providing it as an output parameter is an optimization, not a - * requirement. + * vacrel->next_block_state->vmbuffer will contain visibility information for + * the next unskippable heap block. If we decide not to skip this heap block, + * the caller is responsible for fetching the correct VM block into the + * vmbuffer before using it. * * Note: our opinion of which blocks can be skipped can go stale immediately. * It's okay if caller "misses" a page whose all-visible or all-frozen marking @@ -1100,9 +1154,9 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool -heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, bool *all_visible_according_to_vm) +static void +heap_vac_scan_next_block(LVRelState *vacrel, + bool *all_visible_according_to_vm) { /* Relies on InvalidBlockNumber + 1 == 0 */ BlockNumber next_block = vacrel->next_block_state.current_block + 1; @@ -1129,8 +1183,8 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, */ if (next_block >= vacrel->rel_pages) { - vacrel->next_block_state.current_block = *blkno = InvalidBlockNumber; - return false; + vacrel->next_block_state.current_block = InvalidBlockNumber; + return; } if (vacrel->next_block_state.next_unskippable_block == InvalidBlockNumber || @@ -1144,7 +1198,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, { uint8 mapbits = visibilitymap_get_status(vacrel->rel, next_unskippable_block, - vmbuffer); + &vacrel->next_block_state.next_unskippable_vmbuffer); vacrel->next_block_state.next_unskippable_allvis = mapbits & VISIBILITYMAP_ALL_VISIBLE; @@ -1224,8 +1278,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, else *all_visible_according_to_vm = true; - vacrel->next_block_state.current_block = *blkno = next_block; - return true; + vacrel->next_block_state.current_block = next_block; } /* -- 2.40.1 --3uc3jkcn3zcvmfik Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v7-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_next_block(). --- src/backend/access/heap/vacuumlazy.c | 131 +++++++++++++++++++-------- 1 file changed, 92 insertions(+), 39 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index d2c8f27fc57..d07a2a58b15 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -220,6 +226,12 @@ typedef struct LVRelState BlockNumber next_unskippable_block; /* Next unskippable block's visibility status */ bool next_unskippable_allvis; + + /* + * Buffer containing block of VM with visibility information for + * next_unskippable_block. + */ + Buffer next_unskippable_vmbuffer; } next_block_state; } LVRelState; @@ -233,8 +245,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, +static void heap_vac_scan_next_block(LVRelState *vacrel, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, @@ -777,6 +788,47 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + heap_vac_scan_next_block(vacrel, + all_visible_according_to_vm); + + /* + * If there are no further blocks to vacuum in the relation, release the + * vmbuffer. + */ + if (!BlockNumberIsValid(vacrel->next_block_state.current_block) && + BufferIsValid(vacrel->next_block_state.next_unskippable_vmbuffer)) + { + ReleaseBuffer(vacrel->next_block_state.next_unskippable_vmbuffer); + vacrel->next_block_state.next_unskippable_vmbuffer = InvalidBuffer; + } + + return vacrel->next_block_state.current_block; +} + +static inline PgStreamingRead * +vac_scan_pgsr_alloc(LVRelState *vacrel, PgStreamingReadBufferCB next_block_cb) +{ + PgStreamingRead *result = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, next_block_cb); + + /* + * Initialize for first heap_vac_scan_next_block() call. These rely on + * InvalidBlockNumber + 1 = 0 + */ + vacrel->next_block_state.current_block = InvalidBlockNumber; + vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; + + return result; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -816,10 +868,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, - blkno, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; VacDeadItems *dead_items = vacrel->dead_items; Buffer vmbuffer = InvalidBuffer; @@ -830,23 +882,27 @@ lazy_scan_heap(LVRelState *vacrel) }; int64 initprog_val[3]; + PgStreamingRead *pgsr = vac_scan_pgsr_alloc(vacrel, vacuum_scan_pgsr_next); + /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; initprog_val[1] = rel_pages; initprog_val[2] = dead_items->max_items; pgstat_progress_update_multi_param(3, initprog_index, initprog_val); - /* Initialize for first heap_vac_scan_next_block() call */ - vacrel->next_block_state.current_block = InvalidBlockNumber; - vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; - - while (heap_vac_scan_next_block(vacrel, &vmbuffer, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = pg_streaming_read_buffer_get_next(pgsr, + (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -914,9 +970,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -973,7 +1026,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - vmbuffer, all_visible_according_to_vm, + vmbuffer, *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1030,7 +1083,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1045,6 +1098,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1056,11 +1111,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1072,12 +1127,13 @@ lazy_scan_heap(LVRelState *vacrel) * * lazy_scan_heap() calls here every time it needs to get the next block to * prune and vacuum, using the visibility map, vacuum options, and various - * thresholds to skip blocks which do not need to be processed and set blkno to - * the next block that actually needs to be processed. + * thresholds to skip blocks which do not need to be processed and set + * current_block to the next block that actually needs to be processed. * - * The block number and visibility status of the next block to process are set - * in blkno and all_visible_according_to_vm. heap_vac_scan_next_block() - * returns false if there are no further blocks to process. + * The number and visibility status of the next block to process are set in + * vacrel->next_block_state->current_block and all_visible_according_to_vm. + * vacrel->next_block_state->current_block is set to InvalidBlockNumber if + * there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read, members of vacrel->next_block_state are read and set as @@ -1085,12 +1141,10 @@ lazy_scan_heap(LVRelState *vacrel) * don't advance relfrozenxid when we have skipped vacuuming all-visible * blocks. * - * vmbuffer is an output parameter which, upon return, will contain the block - * from the VM containing visibility information for the next unskippable heap - * block. If we decide not to skip this heap block, the caller is responsible - * for fetching the correct VM block into vmbuffer before using it. This is - * okay as providing it as an output parameter is an optimization, not a - * requirement. + * vacrel->next_block_state->vmbuffer will contain visibility information for + * the next unskippable heap block. If we decide not to skip this heap block, + * the caller is responsible for fetching the correct VM block into the + * vmbuffer before using it. * * Note: our opinion of which blocks can be skipped can go stale immediately. * It's okay if caller "misses" a page whose all-visible or all-frozen marking @@ -1100,9 +1154,9 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool -heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, bool *all_visible_according_to_vm) +static void +heap_vac_scan_next_block(LVRelState *vacrel, + bool *all_visible_according_to_vm) { /* Relies on InvalidBlockNumber + 1 == 0 */ BlockNumber next_block = vacrel->next_block_state.current_block + 1; @@ -1129,8 +1183,8 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, */ if (next_block >= vacrel->rel_pages) { - vacrel->next_block_state.current_block = *blkno = InvalidBlockNumber; - return false; + vacrel->next_block_state.current_block = InvalidBlockNumber; + return; } if (vacrel->next_block_state.next_unskippable_block == InvalidBlockNumber || @@ -1144,7 +1198,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, { uint8 mapbits = visibilitymap_get_status(vacrel->rel, next_unskippable_block, - vmbuffer); + &vacrel->next_block_state.next_unskippable_vmbuffer); vacrel->next_block_state.next_unskippable_allvis = mapbits & VISIBILITYMAP_ALL_VISIBLE; @@ -1224,8 +1278,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, else *all_visible_according_to_vm = true; - vacrel->next_block_state.current_block = *blkno = next_block; - return true; + vacrel->next_block_state.current_block = next_block; } /* -- 2.40.1 --3uc3jkcn3zcvmfik Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v7-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_next_block(). --- src/backend/access/heap/vacuumlazy.c | 131 +++++++++++++++++++-------- 1 file changed, 92 insertions(+), 39 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index d2c8f27fc57..d07a2a58b15 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -220,6 +226,12 @@ typedef struct LVRelState BlockNumber next_unskippable_block; /* Next unskippable block's visibility status */ bool next_unskippable_allvis; + + /* + * Buffer containing block of VM with visibility information for + * next_unskippable_block. + */ + Buffer next_unskippable_vmbuffer; } next_block_state; } LVRelState; @@ -233,8 +245,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, +static void heap_vac_scan_next_block(LVRelState *vacrel, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, @@ -777,6 +788,47 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + heap_vac_scan_next_block(vacrel, + all_visible_according_to_vm); + + /* + * If there are no further blocks to vacuum in the relation, release the + * vmbuffer. + */ + if (!BlockNumberIsValid(vacrel->next_block_state.current_block) && + BufferIsValid(vacrel->next_block_state.next_unskippable_vmbuffer)) + { + ReleaseBuffer(vacrel->next_block_state.next_unskippable_vmbuffer); + vacrel->next_block_state.next_unskippable_vmbuffer = InvalidBuffer; + } + + return vacrel->next_block_state.current_block; +} + +static inline PgStreamingRead * +vac_scan_pgsr_alloc(LVRelState *vacrel, PgStreamingReadBufferCB next_block_cb) +{ + PgStreamingRead *result = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, next_block_cb); + + /* + * Initialize for first heap_vac_scan_next_block() call. These rely on + * InvalidBlockNumber + 1 = 0 + */ + vacrel->next_block_state.current_block = InvalidBlockNumber; + vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; + + return result; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -816,10 +868,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, - blkno, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; VacDeadItems *dead_items = vacrel->dead_items; Buffer vmbuffer = InvalidBuffer; @@ -830,23 +882,27 @@ lazy_scan_heap(LVRelState *vacrel) }; int64 initprog_val[3]; + PgStreamingRead *pgsr = vac_scan_pgsr_alloc(vacrel, vacuum_scan_pgsr_next); + /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; initprog_val[1] = rel_pages; initprog_val[2] = dead_items->max_items; pgstat_progress_update_multi_param(3, initprog_index, initprog_val); - /* Initialize for first heap_vac_scan_next_block() call */ - vacrel->next_block_state.current_block = InvalidBlockNumber; - vacrel->next_block_state.next_unskippable_block = InvalidBlockNumber; - - while (heap_vac_scan_next_block(vacrel, &vmbuffer, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = pg_streaming_read_buffer_get_next(pgsr, + (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -914,9 +970,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -973,7 +1026,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - vmbuffer, all_visible_according_to_vm, + vmbuffer, *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1030,7 +1083,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1045,6 +1098,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1056,11 +1111,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1072,12 +1127,13 @@ lazy_scan_heap(LVRelState *vacrel) * * lazy_scan_heap() calls here every time it needs to get the next block to * prune and vacuum, using the visibility map, vacuum options, and various - * thresholds to skip blocks which do not need to be processed and set blkno to - * the next block that actually needs to be processed. + * thresholds to skip blocks which do not need to be processed and set + * current_block to the next block that actually needs to be processed. * - * The block number and visibility status of the next block to process are set - * in blkno and all_visible_according_to_vm. heap_vac_scan_next_block() - * returns false if there are no further blocks to process. + * The number and visibility status of the next block to process are set in + * vacrel->next_block_state->current_block and all_visible_according_to_vm. + * vacrel->next_block_state->current_block is set to InvalidBlockNumber if + * there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read, members of vacrel->next_block_state are read and set as @@ -1085,12 +1141,10 @@ lazy_scan_heap(LVRelState *vacrel) * don't advance relfrozenxid when we have skipped vacuuming all-visible * blocks. * - * vmbuffer is an output parameter which, upon return, will contain the block - * from the VM containing visibility information for the next unskippable heap - * block. If we decide not to skip this heap block, the caller is responsible - * for fetching the correct VM block into vmbuffer before using it. This is - * okay as providing it as an output parameter is an optimization, not a - * requirement. + * vacrel->next_block_state->vmbuffer will contain visibility information for + * the next unskippable heap block. If we decide not to skip this heap block, + * the caller is responsible for fetching the correct VM block into the + * vmbuffer before using it. * * Note: our opinion of which blocks can be skipped can go stale immediately. * It's okay if caller "misses" a page whose all-visible or all-frozen marking @@ -1100,9 +1154,9 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool -heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, - BlockNumber *blkno, bool *all_visible_according_to_vm) +static void +heap_vac_scan_next_block(LVRelState *vacrel, + bool *all_visible_according_to_vm) { /* Relies on InvalidBlockNumber + 1 == 0 */ BlockNumber next_block = vacrel->next_block_state.current_block + 1; @@ -1129,8 +1183,8 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, */ if (next_block >= vacrel->rel_pages) { - vacrel->next_block_state.current_block = *blkno = InvalidBlockNumber; - return false; + vacrel->next_block_state.current_block = InvalidBlockNumber; + return; } if (vacrel->next_block_state.next_unskippable_block == InvalidBlockNumber || @@ -1144,7 +1198,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, { uint8 mapbits = visibilitymap_get_status(vacrel->rel, next_unskippable_block, - vmbuffer); + &vacrel->next_block_state.next_unskippable_vmbuffer); vacrel->next_block_state.next_unskippable_allvis = mapbits & VISIBILITYMAP_ALL_VISIBLE; @@ -1224,8 +1278,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, Buffer *vmbuffer, else *all_visible_according_to_vm = true; - vacrel->next_block_state.current_block = *blkno = next_block; - return true; + vacrel->next_block_state.current_block = next_block; } /* -- 2.40.1 --3uc3jkcn3zcvmfik Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v7-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface @ 2023-12-31 16:29 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Melanie Plageman @ 2023-12-31 16:29 UTC (permalink / raw) Now vacuum's first pass, which HOT prunes and records the TIDs of non-removable dead tuples, uses the streaming read API by implementing a streaming read callback which invokes heap_vac_scan_get_next_block(). --- src/backend/access/heap/vacuumlazy.c | 79 +++++++++++++++++++++------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 65d257aab83..fbbc87938e4 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -54,6 +54,7 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/streaming_read.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_rusage.h" @@ -168,7 +169,12 @@ typedef struct LVRelState char *relnamespace; char *relname; char *indname; /* Current index name */ - BlockNumber blkno; /* used only for heap operations */ + + /* + * The current block being processed by vacuum. Used only for heap + * operations. Primarily for error reporting and logging. + */ + BlockNumber blkno; OffsetNumber offnum; /* used only for heap operations */ VacErrPhase phase; bool verbose; /* VACUUM VERBOSE? */ @@ -189,6 +195,12 @@ typedef struct LVRelState BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ + /* + * The most recent block submitted in the streaming read callback by the + * first vacuum pass. + */ + BlockNumber blkno_prefetch; + /* Statistics output by us, for table */ double new_rel_tuples; /* new estimated total # of tuples */ double new_live_tuples; /* new estimated total # of live tuples */ @@ -232,7 +244,7 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, @@ -416,6 +428,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->nonempty_pages = 0; /* dead_items_alloc allocates vacrel->dead_items later on */ + /* relies on InvalidBlockNumber overflowing to 0 */ + vacrel->blkno_prefetch = InvalidBlockNumber; + /* Allocate/initialize output statistics state */ vacrel->new_rel_tuples = 0; vacrel->new_live_tuples = 0; @@ -776,6 +791,22 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } +static BlockNumber +vacuum_scan_pgsr_next(PgStreamingRead *pgsr, + void *pgsr_private, void *per_buffer_data) +{ + LVRelState *vacrel = pgsr_private; + bool *all_visible_according_to_vm = per_buffer_data; + + vacrel->blkno_prefetch++; + + heap_vac_scan_get_next_block(vacrel, + vacrel->blkno_prefetch, &vacrel->blkno_prefetch, + all_visible_according_to_vm); + + return vacrel->blkno_prefetch; +} + /* * lazy_scan_heap() -- workhorse function for VACUUM * @@ -815,12 +846,11 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + Buffer buf; BlockNumber rel_pages = vacrel->rel_pages, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; + bool *all_visible_according_to_vm; - /* relies on InvalidBlockNumber overflowing to 0 */ - BlockNumber blkno = InvalidBlockNumber; VacDeadItems *dead_items = vacrel->dead_items; const int initprog_index[] = { PROGRESS_VACUUM_PHASE, @@ -828,6 +858,11 @@ lazy_scan_heap(LVRelState *vacrel) PROGRESS_VACUUM_MAX_DEAD_TUPLES }; int64 initprog_val[3]; + PgStreamingRead *pgsr; + + pgsr = pg_streaming_read_buffer_alloc(PGSR_FLAG_MAINTENANCE, vacrel, + sizeof(bool), vacrel->bstrategy, BMR_REL(vacrel->rel), + MAIN_FORKNUM, vacuum_scan_pgsr_next); /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; @@ -838,13 +873,19 @@ lazy_scan_heap(LVRelState *vacrel) vacrel->skip.next_unskippable_block = InvalidBlockNumber; vacrel->skip.vmbuffer = InvalidBuffer; - while (heap_vac_scan_get_next_block(vacrel, blkno + 1, - &blkno, &all_visible_according_to_vm)) + while (BufferIsValid(buf = + pg_streaming_read_buffer_get_next(pgsr, (void **) &all_visible_according_to_vm))) { - Buffer buf; Page page; bool has_lpdead_items; bool got_cleanup_lock = false; + BlockNumber blkno; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + + CheckBufferIsPinnedOnce(buf); + + page = BufferGetPage(buf); vacrel->scanned_pages++; @@ -912,9 +953,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vacrel->skip.vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); /* * We need a buffer cleanup lock to prune HOT chains and defragment @@ -970,7 +1008,7 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - all_visible_according_to_vm, + *all_visible_according_to_vm, &has_lpdead_items); /* @@ -1027,7 +1065,7 @@ lazy_scan_heap(LVRelState *vacrel) } /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, vacrel->rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1042,6 +1080,8 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + pg_streaming_read_free(pgsr); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming @@ -1053,11 +1093,11 @@ lazy_scan_heap(LVRelState *vacrel) * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (vacrel->rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, vacrel->rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, vacrel->rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1090,7 +1130,7 @@ lazy_scan_heap(LVRelState *vacrel) * * The block number and visibility status of the next block to process are set * in blkno and all_visible_according_to_vm. heap_vac_scan_get_next_block() - * returns false if there are no further blocks to process. + * sets blkno to InvalidBlockNumber if there are no further blocks to process. * * vacrel is an in/out parameter here; vacuum options and information about the * relation are read and vacrel->skippedallvis is set to ensure we don't @@ -1110,7 +1150,7 @@ lazy_scan_heap(LVRelState *vacrel) * older XIDs/MXIDs. The vacrel->skippedallvis flag will be set here when the * choice to skip such a range is actually made, making everything safe.) */ -static bool +static void heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, BlockNumber *blkno, bool *all_visible_according_to_vm) { @@ -1119,7 +1159,7 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, if (next_block >= vacrel->rel_pages) { *blkno = InvalidBlockNumber; - return false; + return; } if (vacrel->skip.next_unskippable_block == InvalidBlockNumber || @@ -1214,7 +1254,6 @@ heap_vac_scan_get_next_block(LVRelState *vacrel, BlockNumber next_block, *all_visible_according_to_vm = true; *blkno = next_block; - return true; } /* -- 2.40.1 --lb5e4aqx4b6ik5lq Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v5a-0007-Vacuum-second-pass-uses-Streaming-Read-interface.patch" ^ permalink raw reply [nested|flat] 7+ messages in thread
* RE: AIX support @ 2026-01-29 14:52 Aditya Kamath <[email protected]> 0 siblings, 0 replies; 7+ messages in thread From: Aditya Kamath @ 2026-01-29 14:52 UTC (permalink / raw) To: Andres Freund <[email protected]>; Robert Haas <[email protected]>; Michael Paquier <[email protected]>; +Cc: Srirama Kucherlapati <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]> Hi Andres and Robert, Thank you for your guidance so far. >I'd fix that aspect by doing the same thing in the autoconf build as we do in >meson, i.e. keep the file in the include dir. We already do that e.g. for >guc_tables.inc.c, see this src/backend/utils/Makefile stanza: ># These generated headers must be symlinked into src/include/. ># We use header-stamp to record that we've done this because the symlinks ># themselves may appear older than fmgr-stamp. >$(top_builddir)/src/include/utils/header-stamp: fmgr-stamp errcodes.h >probes.h guc_tables.inc.c > cd '$(dir $@)' && for file in fmgroids.h fmgrprotos.h errcodes.h probes.h >guc_tables.inc.c; do \ > rm -f $$file && $(LN_S) "../../../$(subdir)/$$file" . ; \ > done > touch $@ Thank you for this. We tried this. (Please see patch: fix-GNU-exp.patch) and we were able to compile on both GNU and meson. We also used the patch sent by Robert. (See: dont-include-include-utils.patch) # ls -l ./src/include/utils/wait_event_funcs_data.c lrwxrwxrwx 1 root system 59 Jan 29 06:49 ./src/include/utils/wait_event_funcs_data.c -> ../../../src/backend/utils/activity/wait_event_funcs_data.c This creates the soft link like probes.h # ls -l probes.h lrwxrwxrwx 1 root system 35 Jan 29 06:45 ./src/include/utils/probes.h -> ../../../src/backend/utils/probes.h >The issue here is legitimate, in the >sense that including src/include/utils in the include path for some >file doesn't seem legit to me. But fixing that problem by defining, >just on AIX, the same symbol that the system header defines seems like >clearly the wrong fix. What if we needed to include the actual float.h >somewhere? What if the problem also occurred on some other platform? >Please put a bit more thought into the right ways to (1) describe the >things you find to us and (2) fix them. You're right: adding src/include/utils to the include path was not legitimate and defining _H_FLOAT on AIX was only masking the underlying ordering issue rather than solving it correctly. After re‑evaluating the problem, I agree that the real fix is to go with the way we all along are discussing suggested in the last couple of threads. Hope this works for all of us. Let us know if we missed something or did it wrong. Will send a git format patch for meson build tool after this thread for review which will include all this information and what Tom suggested for the alignment such that one can git apply the patch and build using meson in AIX. Once again thank you for all your inputs. Have a nice day ahead. Thanks and regards, Aditya. From: Andres Freund <[email protected]> Date: Wednesday, 28 January 2026 at 11:03 PM To: Robert Haas <[email protected]>, Michael Paquier <[email protected]> Cc: Aditya Kamath <[email protected]>, Srirama Kucherlapati <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]> Subject: [EXTERNAL] Re: AIX support Hi, On 2026-01-28 10:41:52 -0500, Robert Haas wrote: > On Wed, Jan 28, 2026 at 10:20 AM Aditya Kamath <[email protected]> wrote: > > But here is the catch. It won’t pick the AIX system float.h. It will pick the Postgres "src/include/utilsfloat.h”. > > PostgreSQL's header should always be included as "utils/float.h" and > the system header should always be included as "float.h" (or, well, > <float.h>, presumably). So this confusion should not exist unless the > include paths are messed up. It doesn't seem correct to me that the > include path includes src/include/utils rather than just src/include, > but I see the same thing here: I agree that this is wrong. CCing Michael and Bertrand, they added this in fa88928470b5 and 1e68e43d3f0f. > which happens because of: > > wait_event = static_library('wait_event_names', > waitevent_sources, > dependencies: [backend_code], > include_directories: include_directories('../../../include/utils'), > kwargs: internal_lib_args, > ) > > which happens because wait_event_funcs.c contains: > > #include "wait_event_funcs_data.c" > > and for some reason, that file gets placed in src/include/utils. The reason for that is that the same invocation also generates wait_event_types.h, which is included by other headers. > The attached patch, which also adjusts wait_events.c, fixes it for me. Unfortunately I suspect that'll cause issues with make builds, because there the files are generated in a different place (src/backend/activity) and then only wait_event_types.h is copied to src/include. So including the files as utils/ won't work. I'd fix that aspect by doing the same thing in the autoconf build as we do in meson, i.e. keep the file in the include dir. We already do that e.g. for guc_tables.inc.c, see this src/backend/utils/Makefile stanza: # These generated headers must be symlinked into src/include/. # We use header-stamp to record that we've done this because the symlinks # themselves may appear older than fmgr-stamp. $(top_builddir)/src/include/utils/header-stamp: fmgr-stamp errcodes.h probes.h guc_tables.inc.c cd '$(dir $@)' && for file in fmgroids.h fmgrprotos.h errcodes.h probes.h guc_tables.inc.c; do \ rm -f $$file && $(LN_S) "../../../$(subdir)/$$file" . ; \ done touch $@ Alternatively: I'm not a fan of including .c files that are not actually working C. You could just make wait_event_funcs_data.c be a complete C file, defining waitEventData, that is then built as a standalone file. Greetings, Andres Freund Attachments: [application/octet-stream] fix-GNU-exp.patch (1.2K, ../../LV8PR15MB64885C1A81463FDF46C1E080D69EA@LV8PR15MB6488.namprd15.prod.outlook.com/3-fix-GNU-exp.patch) download | inline diff: diff --git a/src/backend/utils/Makefile b/src/backend/utils/Makefile index 6df31504f32..24a679a94c8 100644 --- a/src/backend/utils/Makefile +++ b/src/backend/utils/Makefile @@ -38,7 +38,7 @@ all: probes.h generated-header-symlinks .PHONY: generated-header-symlinks submake-adt-headers -generated-header-symlinks: $(top_builddir)/src/include/utils/header-stamp submake-adt-headers +generated-header-symlinks: $(top_builddir)/src/include/utils/header-stamp $(top_builddir)/src/include/utils/wait_event-stamp submake-adt-headers submake-adt-headers: $(MAKE) -C adt jsonpath_gram.h @@ -78,6 +78,12 @@ $(top_builddir)/src/include/utils/header-stamp: fmgr-stamp errcodes.h probes.h g rm -f $$file && $(LN_S) "../../../$(subdir)/$$file" . ; \ done touch $@ +# Symlink activity/wait_event_funcs_data.c into src/include/utils/. +# We use wait-event-stamp to ensure the symlink exists and doesn't get regenerated unnecessarily. +$(top_builddir)/src/include/utils/wait_event-stamp: $(top_srcdir)/src/backend/utils/activity/wait_event_funcs_data.c + cd '$(dir $@)' && rm -f wait_event_funcs_data.c && \ + $(LN_S) "$(top_builddir)/$(subdir)/activity/wait_event_funcs_data.c" . + touch $@ .PHONY: install-data install-data: errcodes.txt installdirs [application/octet-stream] dont-include-include-utils.patch (1.3K, ../../LV8PR15MB64885C1A81463FDF46C1E080D69EA@LV8PR15MB6488.namprd15.prod.outlook.com/4-dont-include-include-utils.patch) download | inline diff: diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build index 9f48d5970e1..53bd5a246ca 100644 --- a/src/backend/utils/activity/meson.build +++ b/src/backend/utils/activity/meson.build @@ -30,7 +30,6 @@ waitevent_sources = files( wait_event = static_library('wait_event_names', waitevent_sources, dependencies: [backend_code], - include_directories: include_directories('../../../include/utils'), kwargs: internal_lib_args, ) diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c index e4f2c440257..aca2c8fc742 100644 --- a/src/backend/utils/activity/wait_event.c +++ b/src/backend/utils/activity/wait_event.c @@ -503,4 +503,4 @@ pgstat_get_wait_event(uint32 wait_event_info) return event_name; } -#include "pgstat_wait_event.c" +#include "utils/pgstat_wait_event.c" diff --git a/src/backend/utils/activity/wait_event_funcs.c b/src/backend/utils/activity/wait_event_funcs.c index b62ee83ef73..fa10a80b088 100644 --- a/src/backend/utils/activity/wait_event_funcs.c +++ b/src/backend/utils/activity/wait_event_funcs.c @@ -31,7 +31,7 @@ static const struct waitEventData[] = { -#include "wait_event_funcs_data.c" +#include "utils/wait_event_funcs_data.c" /* end of list */ {NULL, NULL, NULL} }; ^ permalink raw reply [nested|flat] 7+ messages in thread
end of thread, other threads:[~2026-01-29 14:52 UTC | newest] Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2023-12-31 16:29 [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2023-12-31 16:29 [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2023-12-31 16:29 [PATCH v5a 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2023-12-31 16:29 [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2023-12-31 16:29 [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2023-12-31 16:29 [PATCH v7 6/7] Vacuum first pass uses Streaming Read interface Melanie Plageman <[email protected]> 2026-01-29 14:52 RE: AIX support Aditya Kamath <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox