LCOV - differential code coverage report
Current view: top level - contrib/bloom - blvacuum.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 98.6 % 72 71 1 71
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 2 2 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * blvacuum.c
       4                 :  *      Bloom VACUUM functions.
       5                 :  *
       6                 :  * Copyright (c) 2016-2023, 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 "catalog/storage.h"
      18                 : #include "commands/vacuum.h"
      19                 : #include "miscadmin.h"
      20                 : #include "postmaster/autovacuum.h"
      21                 : #include "storage/bufmgr.h"
      22                 : #include "storage/indexfsm.h"
      23                 : #include "storage/lmgr.h"
      24                 : 
      25                 : 
      26                 : /*
      27                 :  * Bulk deletion of all index entries pointing to a set of heap tuples.
      28                 :  * The set of target tuples is specified via a callback routine that tells
      29                 :  * whether any given heap tuple (identified by ItemPointer) is being deleted.
      30                 :  *
      31                 :  * Result: a palloc'd struct containing statistical info for VACUUM displays.
      32                 :  */
      33                 : IndexBulkDeleteResult *
      34 CBC          11 : blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
      35                 :              IndexBulkDeleteCallback callback, void *callback_state)
      36                 : {
      37              11 :     Relation    index = info->index;
      38                 :     BlockNumber blkno,
      39                 :                 npages;
      40                 :     FreeBlockNumberArray notFullPage;
      41              11 :     int         countPage = 0;
      42                 :     BloomState  state;
      43                 :     Buffer      buffer;
      44                 :     Page        page;
      45                 :     BloomMetaPageData *metaData;
      46                 :     GenericXLogState *gxlogState;
      47                 : 
      48              11 :     if (stats == NULL)
      49              11 :         stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
      50                 : 
      51              11 :     initBloomState(&state, index);
      52                 : 
      53                 :     /*
      54                 :      * Iterate over the pages. We don't care about concurrently added pages,
      55                 :      * they can't contain tuples to delete.
      56                 :      */
      57              11 :     npages = RelationGetNumberOfBlocks(index);
      58            1800 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
      59                 :     {
      60                 :         BloomTuple *itup,
      61                 :                    *itupPtr,
      62                 :                    *itupEnd;
      63                 : 
      64            1789 :         vacuum_delay_point();
      65                 : 
      66            1789 :         buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno,
      67                 :                                     RBM_NORMAL, info->strategy);
      68                 : 
      69            1789 :         LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
      70            1789 :         gxlogState = GenericXLogStart(index);
      71            1789 :         page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
      72                 : 
      73                 :         /* Ignore empty/deleted pages until blvacuumcleanup() */
      74            1789 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
      75                 :         {
      76               4 :             UnlockReleaseBuffer(buffer);
      77               4 :             GenericXLogAbort(gxlogState);
      78               4 :             continue;
      79                 :         }
      80                 : 
      81                 :         /*
      82                 :          * Iterate over the tuples.  itup points to current tuple being
      83                 :          * scanned, itupPtr points to where to save next non-deleted tuple.
      84                 :          */
      85            1785 :         itup = itupPtr = BloomPageGetTuple(&state, page, FirstOffsetNumber);
      86            1785 :         itupEnd = BloomPageGetTuple(&state, page,
      87                 :                                     OffsetNumberNext(BloomPageGetMaxOffset(page)));
      88          823785 :         while (itup < itupEnd)
      89                 :         {
      90                 :             /* Do we have to delete this tuple? */
      91          822000 :             if (callback(&itup->heapPtr, callback_state))
      92                 :             {
      93                 :                 /* Yes; adjust count of tuples that will be left on page */
      94          129621 :                 BloomPageGetOpaque(page)->maxoff--;
      95          129621 :                 stats->tuples_removed += 1;
      96                 :             }
      97                 :             else
      98                 :             {
      99                 :                 /* No; copy it to itupPtr++, but skip copy if not needed */
     100          692379 :                 if (itupPtr != itup)
     101          690375 :                     memmove((Pointer) itupPtr, (Pointer) itup,
     102                 :                             state.sizeOfBloomTuple);
     103          692379 :                 itupPtr = BloomPageGetNextTuple(&state, itupPtr);
     104                 :             }
     105                 : 
     106          822000 :             itup = BloomPageGetNextTuple(&state, itup);
     107                 :         }
     108                 : 
     109                 :         /* Assert that we counted correctly */
     110            1785 :         Assert(itupPtr == BloomPageGetTuple(&state, page,
     111                 :                                             OffsetNumberNext(BloomPageGetMaxOffset(page))));
     112                 : 
     113                 :         /*
     114                 :          * Add page to new notFullPage list if we will not mark page as
     115                 :          * deleted and there is free space on it
     116                 :          */
     117            1785 :         if (BloomPageGetMaxOffset(page) != 0 &&
     118            1781 :             BloomPageGetFreeSpace(&state, page) >= state.sizeOfBloomTuple &&
     119            1778 :             countPage < BloomMetaBlockN)
     120            1778 :             notFullPage[countPage++] = blkno;
     121                 : 
     122                 :         /* Did we delete something? */
     123            1785 :         if (itupPtr != itup)
     124                 :         {
     125                 :             /* Is it empty page now? */
     126            1781 :             if (BloomPageGetMaxOffset(page) == 0)
     127               4 :                 BloomPageSetDeleted(page);
     128                 :             /* Adjust pd_lower */
     129            1781 :             ((PageHeader) page)->pd_lower = (Pointer) itupPtr - page;
     130                 :             /* Finish WAL-logging */
     131            1781 :             GenericXLogFinish(gxlogState);
     132                 :         }
     133                 :         else
     134                 :         {
     135                 :             /* Didn't change anything: abort WAL-logging */
     136               4 :             GenericXLogAbort(gxlogState);
     137                 :         }
     138            1785 :         UnlockReleaseBuffer(buffer);
     139                 :     }
     140                 : 
     141                 :     /*
     142                 :      * Update the metapage's notFullPage list with whatever we found.  Our
     143                 :      * info could already be out of date at this point, but blinsert() will
     144                 :      * cope if so.
     145                 :      */
     146              11 :     buffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
     147              11 :     LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
     148                 : 
     149              11 :     gxlogState = GenericXLogStart(index);
     150              11 :     page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
     151                 : 
     152              11 :     metaData = BloomPageGetMeta(page);
     153              11 :     memcpy(metaData->notFullPage, notFullPage, sizeof(BlockNumber) * countPage);
     154              11 :     metaData->nStart = 0;
     155              11 :     metaData->nEnd = countPage;
     156                 : 
     157              11 :     GenericXLogFinish(gxlogState);
     158              11 :     UnlockReleaseBuffer(buffer);
     159                 : 
     160              11 :     return stats;
     161                 : }
     162                 : 
     163                 : /*
     164                 :  * Post-VACUUM cleanup.
     165                 :  *
     166                 :  * Result: a palloc'd struct containing statistical info for VACUUM displays.
     167                 :  */
     168                 : IndexBulkDeleteResult *
     169              12 : blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
     170                 : {
     171              12 :     Relation    index = info->index;
     172                 :     BlockNumber npages,
     173                 :                 blkno;
     174                 : 
     175              12 :     if (info->analyze_only)
     176 UBC           0 :         return stats;
     177                 : 
     178 CBC          12 :     if (stats == NULL)
     179               1 :         stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
     180                 : 
     181                 :     /*
     182                 :      * Iterate over the pages: insert deleted pages into FSM and collect
     183                 :      * statistics.
     184                 :      */
     185              12 :     npages = RelationGetNumberOfBlocks(index);
     186              12 :     stats->num_pages = npages;
     187              12 :     stats->pages_free = 0;
     188              12 :     stats->num_index_tuples = 0;
     189            1998 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
     190                 :     {
     191                 :         Buffer      buffer;
     192                 :         Page        page;
     193                 : 
     194            1986 :         vacuum_delay_point();
     195                 : 
     196            1986 :         buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno,
     197                 :                                     RBM_NORMAL, info->strategy);
     198            1986 :         LockBuffer(buffer, BUFFER_LOCK_SHARE);
     199            1986 :         page = (Page) BufferGetPage(buffer);
     200                 : 
     201            1986 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
     202                 :         {
     203               8 :             RecordFreeIndexPage(index, blkno);
     204               8 :             stats->pages_free++;
     205                 :         }
     206                 :         else
     207                 :         {
     208            1978 :             stats->num_index_tuples += BloomPageGetMaxOffset(page);
     209                 :         }
     210                 : 
     211            1986 :         UnlockReleaseBuffer(buffer);
     212                 :     }
     213                 : 
     214              12 :     IndexFreeSpaceMapVacuum(info->index);
     215                 : 
     216              12 :     return stats;
     217                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a