LCOV - differential code coverage report
Current view: top level - contrib/bloom - blvacuum.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DCB
Current: 0e5ff9b9b45a657aea12440478dc002e9b01f138 vs 0123ce131fca454009439dfa3b2266d1d40737d7 Lines: 98.8 % 82 81 1 17 64 7
Current Date: 2026-03-14 14:10:32 -0400 Functions: 100.0 % 2 2 2
Baseline: lcov-20260315-024220-baseline Branches: 80.0 % 40 32 2 6 2 30
Baseline Date: 2026-03-14 15:27:56 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 100.0 % 12 12 12
(30,360] days: 100.0 % 5 5 5
(360..) days: 98.5 % 65 64 1 64
Function coverage date bins:
(360..) days: 100.0 % 2 2 2
Branch coverage date bins:
(1,7] days: 50.0 % 4 2 2 2
(360..) days: 83.3 % 36 30 6 30

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * blvacuum.c
                                  4                 :                :  *      Bloom VACUUM functions.
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2016-2026, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  * IDENTIFICATION
                                  9                 :                :  *    contrib/bloom/blvacuum.c
                                 10                 :                :  *
                                 11                 :                :  *-------------------------------------------------------------------------
                                 12                 :                :  */
                                 13                 :                : #include "postgres.h"
                                 14                 :                : 
                                 15                 :                : #include "access/genam.h"
                                 16                 :                : #include "bloom.h"
                                 17                 :                : #include "commands/vacuum.h"
                                 18                 :                : #include "storage/bufmgr.h"
                                 19                 :                : #include "storage/indexfsm.h"
                                 20                 :                : #include "storage/read_stream.h"
                                 21                 :                : 
                                 22                 :                : 
                                 23                 :                : /*
                                 24                 :                :  * Bulk deletion of all index entries pointing to a set of heap tuples.
                                 25                 :                :  * The set of target tuples is specified via a callback routine that tells
                                 26                 :                :  * whether any given heap tuple (identified by ItemPointer) is being deleted.
                                 27                 :                :  *
                                 28                 :                :  * Result: a palloc'd struct containing statistical info for VACUUM displays.
                                 29                 :                :  */
                                 30                 :                : IndexBulkDeleteResult *
 3635 teodor@sigaev.ru           31                 :CBC          11 : blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
                                 32                 :                :              IndexBulkDeleteCallback callback, void *callback_state)
                                 33                 :                : {
                                 34                 :             11 :     Relation    index = info->index;
                                 35                 :                :     BlockNumber blkno,
                                 36                 :                :                 npages;
                                 37                 :                :     FreeBlockNumberArray notFullPage;
                                 38                 :             11 :     int         countPage = 0;
                                 39                 :                :     BloomState  state;
                                 40                 :                :     Buffer      buffer;
                                 41                 :                :     Page        page;
                                 42                 :                :     BloomMetaPageData *metaData;
                                 43                 :                :     GenericXLogState *gxlogState;
                                 44                 :                :     BlockRangeReadStreamPrivate p;
                                 45                 :                :     ReadStream *stream;
                                 46                 :                : 
                                 47         [ +  - ]:             11 :     if (stats == NULL)
  100 michael@paquier.xyz        48                 :GNC          11 :         stats = palloc0_object(IndexBulkDeleteResult);
                                 49                 :                : 
 3635 teodor@sigaev.ru           50                 :CBC          11 :     initBloomState(&state, index);
                                 51                 :                : 
                                 52                 :                :     /*
                                 53                 :                :      * Iterate over the pages. We don't care about concurrently added pages,
                                 54                 :                :      * they can't contain tuples to delete.
                                 55                 :                :      */
                                 56                 :             11 :     npages = RelationGetNumberOfBlocks(index);
                                 57                 :                : 
                                 58                 :                :     /* Scan all blocks except the metapage using streaming reads */
    3 michael@paquier.xyz        59                 :GNC          11 :     p.current_blocknum = BLOOM_HEAD_BLKNO;
                                 60                 :             11 :     p.last_exclusive = npages;
                                 61                 :                : 
                                 62                 :                :     /*
                                 63                 :                :      * It is safe to use batchmode as block_range_read_stream_cb takes no
                                 64                 :                :      * locks.
                                 65                 :                :      */
                                 66                 :             11 :     stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE |
                                 67                 :                :                                         READ_STREAM_FULL |
                                 68                 :                :                                         READ_STREAM_USE_BATCHING,
                                 69                 :                :                                         info->strategy,
                                 70                 :                :                                         index,
                                 71                 :                :                                         MAIN_FORKNUM,
                                 72                 :                :                                         block_range_read_stream_cb,
                                 73                 :                :                                         &p,
                                 74                 :                :                                         0);
                                 75                 :                : 
 3635 teodor@sigaev.ru           76         [ +  + ]:CBC         678 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
                                 77                 :                :     {
                                 78                 :                :         BloomTuple *itup,
                                 79                 :                :                    *itupPtr,
                                 80                 :                :                    *itupEnd;
                                 81                 :                : 
  397 nathan@postgresql.or       82                 :            667 :         vacuum_delay_point(false);
                                 83                 :                : 
    3 michael@paquier.xyz        84                 :GNC         667 :         buffer = read_stream_next_buffer(stream, NULL);
                                 85                 :                : 
 3635 teodor@sigaev.ru           86                 :CBC         667 :         LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
                                 87                 :            667 :         gxlogState = GenericXLogStart(index);
 3624 tgl@sss.pgh.pa.us          88                 :            667 :         page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
                                 89                 :                : 
                                 90                 :                :         /* Ignore empty/deleted pages until blvacuumcleanup() */
 3501                            91   [ +  -  +  + ]:            667 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
                                 92                 :                :         {
 3635 teodor@sigaev.ru           93                 :              4 :             UnlockReleaseBuffer(buffer);
 3634                            94                 :              4 :             GenericXLogAbort(gxlogState);
 3635                            95                 :              4 :             continue;
                                 96                 :                :         }
                                 97                 :                : 
                                 98                 :                :         /*
                                 99                 :                :          * Iterate over the tuples.  itup points to current tuple being
                                100                 :                :          * scanned, itupPtr points to where to save next non-deleted tuple.
                                101                 :                :          */
 3634                           102                 :            663 :         itup = itupPtr = BloomPageGetTuple(&state, page, FirstOffsetNumber);
                                103                 :            663 :         itupEnd = BloomPageGetTuple(&state, page,
                                104                 :                :                                     OffsetNumberNext(BloomPageGetMaxOffset(page)));
 3635                           105         [ +  + ]:         336663 :         while (itup < itupEnd)
                                106                 :                :         {
                                107                 :                :             /* Do we have to delete this tuple? */
                                108         [ +  + ]:         336000 :             if (callback(&itup->heapPtr, callback_state))
                                109                 :                :             {
                                110                 :                :                 /* Yes; adjust count of tuples that will be left on page */
                                111                 :          48625 :                 BloomPageGetOpaque(page)->maxoff--;
 3501 tgl@sss.pgh.pa.us         112                 :          48625 :                 stats->tuples_removed += 1;
                                113                 :                :             }
                                114                 :                :             else
                                115                 :                :             {
                                116                 :                :                 /* No; copy it to itupPtr++, but skip copy if not needed */
 3635 teodor@sigaev.ru          117         [ +  + ]:         287375 :                 if (itupPtr != itup)
  102 peter@eisentraut.org      118                 :GNC      284079 :                     memmove(itupPtr, itup, state.sizeOfBloomTuple);
 3635 teodor@sigaev.ru          119                 :CBC      287375 :                 itupPtr = BloomPageGetNextTuple(&state, itupPtr);
                                120                 :                :             }
                                121                 :                : 
                                122                 :         336000 :             itup = BloomPageGetNextTuple(&state, itup);
                                123                 :                :         }
                                124                 :                : 
                                125                 :                :         /* Assert that we counted correctly */
 3634                           126         [ -  + ]:            663 :         Assert(itupPtr == BloomPageGetTuple(&state, page,
                                127                 :                :                                             OffsetNumberNext(BloomPageGetMaxOffset(page))));
                                128                 :                : 
                                129                 :                :         /*
                                130                 :                :          * Add page to new notFullPage list if we will not mark page as
                                131                 :                :          * deleted and there is free space on it
                                132                 :                :          */
                                133         [ +  + ]:            663 :         if (BloomPageGetMaxOffset(page) != 0 &&
 3501 tgl@sss.pgh.pa.us         134         [ +  + ]:            659 :             BloomPageGetFreeSpace(&state, page) >= state.sizeOfBloomTuple &&
 3635 teodor@sigaev.ru          135         [ +  - ]:            656 :             countPage < BloomMetaBlockN)
                                136                 :            656 :             notFullPage[countPage++] = blkno;
                                137                 :                : 
                                138                 :                :         /* Did we delete something? */
                                139         [ +  + ]:            663 :         if (itupPtr != itup)
                                140                 :                :         {
                                141                 :                :             /* Is it empty page now? */
 3634                           142         [ +  + ]:            659 :             if (BloomPageGetMaxOffset(page) == 0)
 3635                           143                 :              4 :                 BloomPageSetDeleted(page);
                                144                 :                :             /* Adjust pd_lower */
  102 peter@eisentraut.org      145                 :GNC         659 :             ((PageHeader) page)->pd_lower = (char *) itupPtr - page;
                                146                 :                :             /* Finish WAL-logging */
 3635 teodor@sigaev.ru          147                 :CBC         659 :             GenericXLogFinish(gxlogState);
                                148                 :                :         }
                                149                 :                :         else
                                150                 :                :         {
                                151                 :                :             /* Didn't change anything: abort WAL-logging */
                                152                 :              4 :             GenericXLogAbort(gxlogState);
                                153                 :                :         }
                                154                 :            663 :         UnlockReleaseBuffer(buffer);
                                155                 :                :     }
                                156                 :                : 
    3 michael@paquier.xyz       157         [ -  + ]:GNC          11 :     Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
                                158                 :             11 :     read_stream_end(stream);
                                159                 :                : 
                                160                 :                :     /*
                                161                 :                :      * Update the metapage's notFullPage list with whatever we found.  Our
                                162                 :                :      * info could already be out of date at this point, but blinsert() will
                                163                 :                :      * cope if so.
                                164                 :                :      */
 3501 tgl@sss.pgh.pa.us         165                 :CBC          11 :     buffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
                                166                 :             11 :     LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
                                167                 :                : 
                                168                 :             11 :     gxlogState = GenericXLogStart(index);
                                169                 :             11 :     page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
                                170                 :                : 
                                171                 :             11 :     metaData = BloomPageGetMeta(page);
                                172                 :             11 :     memcpy(metaData->notFullPage, notFullPage, sizeof(BlockNumber) * countPage);
                                173                 :             11 :     metaData->nStart = 0;
                                174                 :             11 :     metaData->nEnd = countPage;
                                175                 :                : 
                                176                 :             11 :     GenericXLogFinish(gxlogState);
                                177                 :             11 :     UnlockReleaseBuffer(buffer);
                                178                 :                : 
 3635 teodor@sigaev.ru          179                 :             11 :     return stats;
                                180                 :                : }
                                181                 :                : 
                                182                 :                : /*
                                183                 :                :  * Post-VACUUM cleanup.
                                184                 :                :  *
                                185                 :                :  * Result: a palloc'd struct containing statistical info for VACUUM displays.
                                186                 :                :  */
                                187                 :                : IndexBulkDeleteResult *
                                188                 :             12 : blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
                                189                 :                : {
                                190                 :             12 :     Relation    index = info->index;
                                191                 :                :     BlockNumber npages,
                                192                 :                :                 blkno;
                                193                 :                :     BlockRangeReadStreamPrivate p;
                                194                 :                :     ReadStream *stream;
                                195                 :                : 
                                196         [ -  + ]:             12 :     if (info->analyze_only)
 3635 teodor@sigaev.ru          197                 :UBC           0 :         return stats;
                                198                 :                : 
 3635 teodor@sigaev.ru          199         [ +  + ]:CBC          12 :     if (stats == NULL)
  100 michael@paquier.xyz       200                 :GNC           1 :         stats = palloc0_object(IndexBulkDeleteResult);
                                201                 :                : 
                                202                 :                :     /*
                                203                 :                :      * Iterate over the pages: insert deleted pages into FSM and collect
                                204                 :                :      * statistics.
                                205                 :                :      */
 3635 teodor@sigaev.ru          206                 :CBC          12 :     npages = RelationGetNumberOfBlocks(index);
 3501 tgl@sss.pgh.pa.us         207                 :             12 :     stats->num_pages = npages;
                                208                 :             12 :     stats->pages_free = 0;
                                209                 :             12 :     stats->num_index_tuples = 0;
                                210                 :                : 
                                211                 :                :     /* Scan all blocks except the metapage using streaming reads */
    3 michael@paquier.xyz       212                 :GNC          12 :     p.current_blocknum = BLOOM_HEAD_BLKNO;
                                213                 :             12 :     p.last_exclusive = npages;
                                214                 :                : 
                                215                 :                :     /*
                                216                 :                :      * It is safe to use batchmode as block_range_read_stream_cb takes no
                                217                 :                :      * locks.
                                218                 :                :      */
                                219                 :             12 :     stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE |
                                220                 :                :                                         READ_STREAM_FULL |
                                221                 :                :                                         READ_STREAM_USE_BATCHING,
                                222                 :                :                                         info->strategy,
                                223                 :                :                                         index,
                                224                 :                :                                         MAIN_FORKNUM,
                                225                 :                :                                         block_range_read_stream_cb,
                                226                 :                :                                         &p,
                                227                 :                :                                         0);
                                228                 :                : 
 3635 teodor@sigaev.ru          229         [ +  + ]:CBC         787 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
                                230                 :                :     {
                                231                 :                :         Buffer      buffer;
                                232                 :                :         Page        page;
                                233                 :                : 
  397 nathan@postgresql.or      234                 :            775 :         vacuum_delay_point(false);
                                235                 :                : 
    3 michael@paquier.xyz       236                 :GNC         775 :         buffer = read_stream_next_buffer(stream, NULL);
 3635 teodor@sigaev.ru          237                 :CBC         775 :         LockBuffer(buffer, BUFFER_LOCK_SHARE);
  198 peter@eisentraut.org      238                 :GNC         775 :         page = BufferGetPage(buffer);
                                239                 :                : 
 3501 tgl@sss.pgh.pa.us         240   [ +  -  +  + ]:CBC         775 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
                                241                 :                :         {
 3635 teodor@sigaev.ru          242                 :              8 :             RecordFreeIndexPage(index, blkno);
 3501 tgl@sss.pgh.pa.us         243                 :              8 :             stats->pages_free++;
                                244                 :                :         }
                                245                 :                :         else
                                246                 :                :         {
 3635 teodor@sigaev.ru          247                 :            767 :             stats->num_index_tuples += BloomPageGetMaxOffset(page);
                                248                 :                :         }
                                249                 :                : 
                                250                 :            775 :         UnlockReleaseBuffer(buffer);
                                251                 :                :     }
                                252                 :                : 
    3 michael@paquier.xyz       253         [ -  + ]:GNC          12 :     Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
                                254                 :             12 :     read_stream_end(stream);
                                255                 :                : 
 3635 teodor@sigaev.ru          256                 :CBC          12 :     IndexFreeSpaceMapVacuum(info->index);
                                257                 :                : 
                                258                 :             12 :     return stats;
                                259                 :                : }
        

Generated by: LCOV version 2.4-beta