LCOV - differential code coverage report
Current view: top level - contrib/bloom - blinsert.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 92.4 % 119 110 9 110
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 7 7 7
Baseline: 16@8cea358b128 Branches: 54.8 % 42 23 19 23
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (180,240] days: 100.0 % 2 2 2
(240..) days: 92.3 % 117 108 9 108
Function coverage date bins:
(240..) days: 100.0 % 7 7 7
Branch coverage date bins:
(240..) days: 54.8 % 42 23 19 23

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * blinsert.c
                                  4                 :                :  *      Bloom index build and insert functions.
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2016-2024, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  * IDENTIFICATION
                                  9                 :                :  *    contrib/bloom/blinsert.c
                                 10                 :                :  *
                                 11                 :                :  *-------------------------------------------------------------------------
                                 12                 :                :  */
                                 13                 :                : #include "postgres.h"
                                 14                 :                : 
                                 15                 :                : #include "access/genam.h"
                                 16                 :                : #include "access/generic_xlog.h"
                                 17                 :                : #include "access/tableam.h"
                                 18                 :                : #include "bloom.h"
                                 19                 :                : #include "catalog/index.h"
                                 20                 :                : #include "miscadmin.h"
                                 21                 :                : #include "storage/bufmgr.h"
                                 22                 :                : #include "storage/indexfsm.h"
                                 23                 :                : #include "storage/smgr.h"
                                 24                 :                : #include "utils/memutils.h"
                                 25                 :                : #include "utils/rel.h"
                                 26                 :                : 
 2935 teodor@sigaev.ru           27                 :CBC          95 : PG_MODULE_MAGIC;
                                 28                 :                : 
                                 29                 :                : /*
                                 30                 :                :  * State of bloom index build.  We accumulate one page data here before
                                 31                 :                :  * flushing it to buffer manager.
                                 32                 :                :  */
                                 33                 :                : typedef struct
                                 34                 :                : {
                                 35                 :                :     BloomState  blstate;        /* bloom index state */
                                 36                 :                :     int64       indtuples;      /* total number of tuples indexed */
                                 37                 :                :     MemoryContext tmpCtx;       /* temporary memory context reset after each
                                 38                 :                :                                  * tuple */
                                 39                 :                :     PGAlignedBlock data;        /* cached page */
                                 40                 :                :     int         count;          /* number of tuples in cached page */
                                 41                 :                : } BloomBuildState;
                                 42                 :                : 
                                 43                 :                : /*
                                 44                 :                :  * Flush page cached in BloomBuildState.
                                 45                 :                :  */
                                 46                 :                : static void
                                 47                 :             36 : flushCachedPage(Relation index, BloomBuildState *buildstate)
                                 48                 :                : {
                                 49                 :                :     Page        page;
                                 50                 :             36 :     Buffer      buffer = BloomNewBuffer(index);
                                 51                 :                :     GenericXLogState *state;
                                 52                 :                : 
                                 53                 :             36 :     state = GenericXLogStart(index);
 2924 tgl@sss.pgh.pa.us          54                 :             36 :     page = GenericXLogRegisterBuffer(state, buffer, GENERIC_XLOG_FULL_IMAGE);
 2052                            55                 :             36 :     memcpy(page, buildstate->data.data, BLCKSZ);
 2935 teodor@sigaev.ru           56                 :             36 :     GenericXLogFinish(state);
                                 57                 :             36 :     UnlockReleaseBuffer(buffer);
                                 58                 :             36 : }
                                 59                 :                : 
                                 60                 :                : /*
                                 61                 :                :  * (Re)initialize cached page in BloomBuildState.
                                 62                 :                :  */
                                 63                 :                : static void
                                 64                 :             36 : initCachedPage(BloomBuildState *buildstate)
                                 65                 :                : {
 2052 tgl@sss.pgh.pa.us          66                 :             36 :     BloomInitPage(buildstate->data.data, 0);
 2935 teodor@sigaev.ru           67                 :             36 :     buildstate->count = 0;
                                 68                 :             36 : }
                                 69                 :                : 
                                 70                 :                : /*
                                 71                 :                :  * Per-tuple callback for table_index_build_scan.
                                 72                 :                :  */
                                 73                 :                : static void
 1619 andres@anarazel.de         74                 :          18750 : bloomBuildCallback(Relation index, ItemPointer tid, Datum *values,
                                 75                 :                :                    bool *isnull, bool tupleIsAlive, void *state)
                                 76                 :                : {
 2935 teodor@sigaev.ru           77                 :          18750 :     BloomBuildState *buildstate = (BloomBuildState *) state;
                                 78                 :                :     MemoryContext oldCtx;
                                 79                 :                :     BloomTuple *itup;
                                 80                 :                : 
                                 81                 :          18750 :     oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
                                 82                 :                : 
 1619 andres@anarazel.de         83                 :          18750 :     itup = BloomFormTuple(&buildstate->blstate, tid, values, isnull);
                                 84                 :                : 
                                 85                 :                :     /* Try to add next item to cached page */
 2052 tgl@sss.pgh.pa.us          86         [ +  + ]:          18750 :     if (BloomPageAddItem(&buildstate->blstate, buildstate->data.data, itup))
                                 87                 :                :     {
                                 88                 :                :         /* Next item was added successfully */
 2935 teodor@sigaev.ru           89                 :          18719 :         buildstate->count++;
                                 90                 :                :     }
                                 91                 :                :     else
                                 92                 :                :     {
                                 93                 :                :         /* Cached page is full, flush it out and make a new one */
                                 94                 :             31 :         flushCachedPage(index, buildstate);
                                 95                 :                : 
                                 96         [ -  + ]:             31 :         CHECK_FOR_INTERRUPTS();
                                 97                 :                : 
                                 98                 :             31 :         initCachedPage(buildstate);
                                 99                 :                : 
 2052 tgl@sss.pgh.pa.us         100         [ -  + ]:             31 :         if (!BloomPageAddItem(&buildstate->blstate, buildstate->data.data, itup))
                                101                 :                :         {
                                102                 :                :             /* We shouldn't be here since we're inserting to the empty page */
 2933 tgl@sss.pgh.pa.us         103         [ #  # ]:UBC           0 :             elog(ERROR, "could not add new bloom tuple to empty page");
                                104                 :                :         }
                                105                 :                : 
                                106                 :                :         /* Next item was added successfully */
 2215 tgl@sss.pgh.pa.us         107                 :CBC          31 :         buildstate->count++;
                                108                 :                :     }
                                109                 :                : 
                                110                 :                :     /* Update total tuple count */
                                111                 :          18750 :     buildstate->indtuples += 1;
                                112                 :                : 
 2935 teodor@sigaev.ru          113                 :          18750 :     MemoryContextSwitchTo(oldCtx);
                                114                 :          18750 :     MemoryContextReset(buildstate->tmpCtx);
                                115                 :          18750 : }
                                116                 :                : 
                                117                 :                : /*
                                118                 :                :  * Build a new bloom index.
                                119                 :                :  */
                                120                 :                : IndexBuildResult *
                                121                 :              5 : blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
                                122                 :                : {
                                123                 :                :     IndexBuildResult *result;
                                124                 :                :     double      reltuples;
                                125                 :                :     BloomBuildState buildstate;
                                126                 :                : 
                                127         [ -  + ]:              5 :     if (RelationGetNumberOfBlocks(index) != 0)
 2935 teodor@sigaev.ru          128         [ #  # ]:UBC           0 :         elog(ERROR, "index \"%s\" already contains data",
                                129                 :                :              RelationGetRelationName(index));
                                130                 :                : 
                                131                 :                :     /* Initialize the meta page */
  235 heikki.linnakangas@i      132                 :CBC           5 :     BloomInitMetapage(index, MAIN_FORKNUM);
                                133                 :                : 
                                134                 :                :     /* Initialize the bloom build state */
 2935 teodor@sigaev.ru          135                 :              5 :     memset(&buildstate, 0, sizeof(buildstate));
                                136                 :              5 :     initBloomState(&buildstate.blstate, index);
                                137                 :              5 :     buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
                                138                 :                :                                               "Bloom build temporary context",
                                139                 :                :                                               ALLOCSET_DEFAULT_SIZES);
                                140                 :              5 :     initCachedPage(&buildstate);
                                141                 :                : 
                                142                 :                :     /* Do the heap scan */
 1839 alvherre@alvh.no-ip.      143                 :              5 :     reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
                                144                 :                :                                        bloomBuildCallback, (void *) &buildstate,
                                145                 :                :                                        NULL);
                                146                 :                : 
                                147                 :                :     /* Flush last page if needed (it will be, unless heap was empty) */
 2935 teodor@sigaev.ru          148         [ +  - ]:              5 :     if (buildstate.count > 0)
                                149                 :              5 :         flushCachedPage(index, &buildstate);
                                150                 :                : 
                                151                 :              5 :     MemoryContextDelete(buildstate.tmpCtx);
                                152                 :                : 
                                153                 :              5 :     result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
 2215 tgl@sss.pgh.pa.us         154                 :              5 :     result->heap_tuples = reltuples;
                                155                 :              5 :     result->index_tuples = buildstate.indtuples;
                                156                 :                : 
 2935 teodor@sigaev.ru          157                 :              5 :     return result;
                                158                 :                : }
                                159                 :                : 
                                160                 :                : /*
                                161                 :                :  * Build an empty bloom index in the initialization fork.
                                162                 :                :  */
                                163                 :                : void
                                164                 :              1 : blbuildempty(Relation index)
                                165                 :                : {
                                166                 :                :     /* Initialize the meta page */
  235 heikki.linnakangas@i      167                 :              1 :     BloomInitMetapage(index, INIT_FORKNUM);
 2935 teodor@sigaev.ru          168                 :              1 : }
                                169                 :                : 
                                170                 :                : /*
                                171                 :                :  * Insert new tuple to the bloom index.
                                172                 :                :  */
                                173                 :                : bool
                                174                 :         104000 : blinsert(Relation index, Datum *values, bool *isnull,
                                175                 :                :          ItemPointer ht_ctid, Relation heapRel,
                                176                 :                :          IndexUniqueCheck checkUnique,
                                177                 :                :          bool indexUnchanged,
                                178                 :                :          IndexInfo *indexInfo)
                                179                 :                : {
                                180                 :                :     BloomState  blstate;
                                181                 :                :     BloomTuple *itup;
                                182                 :                :     MemoryContext oldCtx;
                                183                 :                :     MemoryContext insertCtx;
                                184                 :                :     BloomMetaPageData *metaData;
                                185                 :                :     Buffer      buffer,
                                186                 :                :                 metaBuffer;
                                187                 :                :     Page        page,
                                188                 :                :                 metaPage;
                                189                 :         104000 :     BlockNumber blkno = InvalidBlockNumber;
                                190                 :                :     OffsetNumber nStart;
                                191                 :                :     GenericXLogState *state;
                                192                 :                : 
                                193                 :         104000 :     insertCtx = AllocSetContextCreate(CurrentMemoryContext,
                                194                 :                :                                       "Bloom insert temporary context",
                                195                 :                :                                       ALLOCSET_DEFAULT_SIZES);
                                196                 :                : 
                                197                 :         104000 :     oldCtx = MemoryContextSwitchTo(insertCtx);
                                198                 :                : 
                                199                 :         104000 :     initBloomState(&blstate, index);
                                200                 :         104000 :     itup = BloomFormTuple(&blstate, ht_ctid, values, isnull);
                                201                 :                : 
                                202                 :                :     /*
                                203                 :                :      * At first, try to insert new tuple to the first page in notFullPage
                                204                 :                :      * array.  If successful, we don't need to modify the meta page.
                                205                 :                :      */
                                206                 :         104000 :     metaBuffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
                                207                 :         104000 :     LockBuffer(metaBuffer, BUFFER_LOCK_SHARE);
 2916 kgrittn@postgresql.o      208                 :         104000 :     metaData = BloomPageGetMeta(BufferGetPage(metaBuffer));
                                209                 :                : 
 2935 teodor@sigaev.ru          210         [ +  + ]:         104000 :     if (metaData->nEnd > metaData->nStart)
                                211                 :                :     {
                                212                 :         103999 :         blkno = metaData->notFullPage[metaData->nStart];
                                213         [ -  + ]:         103999 :         Assert(blkno != InvalidBlockNumber);
                                214                 :                : 
                                215                 :                :         /* Don't hold metabuffer lock while doing insert */
                                216                 :         103999 :         LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
                                217                 :                : 
                                218                 :         103999 :         buffer = ReadBuffer(index, blkno);
                                219                 :         103999 :         LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
                                220                 :                : 
                                221                 :         103999 :         state = GenericXLogStart(index);
 2924 tgl@sss.pgh.pa.us         222                 :         103999 :         page = GenericXLogRegisterBuffer(state, buffer, 0);
                                223                 :                : 
                                224                 :                :         /*
                                225                 :                :          * We might have found a page that was recently deleted by VACUUM.  If
                                226                 :                :          * so, we can reuse it, but we must reinitialize it.
                                227                 :                :          */
 2801                           228   [ +  -  -  + ]:         103999 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
 2801 tgl@sss.pgh.pa.us         229                 :UBC           0 :             BloomInitPage(page, 0);
                                230                 :                : 
 2935 teodor@sigaev.ru          231         [ +  + ]:CBC      103999 :         if (BloomPageAddItem(&blstate, page, itup))
                                232                 :                :         {
                                233                 :                :             /* Success!  Apply the change, clean up, and exit */
                                234                 :         103242 :             GenericXLogFinish(state);
                                235                 :         103242 :             UnlockReleaseBuffer(buffer);
                                236                 :         103242 :             ReleaseBuffer(metaBuffer);
                                237                 :         103242 :             MemoryContextSwitchTo(oldCtx);
                                238                 :         103242 :             MemoryContextDelete(insertCtx);
                                239                 :         103242 :             return false;
                                240                 :                :         }
                                241                 :                : 
                                242                 :                :         /* Didn't fit, must try other pages */
 2927 tgl@sss.pgh.pa.us         243                 :            757 :         GenericXLogAbort(state);
                                244                 :            757 :         UnlockReleaseBuffer(buffer);
                                245                 :                :     }
                                246                 :                :     else
                                247                 :                :     {
                                248                 :                :         /* No entries in notFullPage */
 2935 teodor@sigaev.ru          249                 :              1 :         LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
                                250                 :                :     }
                                251                 :                : 
                                252                 :                :     /*
                                253                 :                :      * Try other pages in notFullPage array.  We will have to change nStart in
                                254                 :                :      * metapage.  Thus, grab exclusive lock on metapage.
                                255                 :                :      */
                                256                 :            758 :     LockBuffer(metaBuffer, BUFFER_LOCK_EXCLUSIVE);
                                257                 :                : 
                                258                 :                :     /* nStart might have changed while we didn't have lock */
                                259                 :            758 :     nStart = metaData->nStart;
                                260                 :                : 
                                261                 :                :     /* Skip first page if we already tried it above */
 2927 tgl@sss.pgh.pa.us         262         [ +  + ]:            758 :     if (nStart < metaData->nEnd &&
 2935 teodor@sigaev.ru          263         [ +  - ]:            757 :         blkno == metaData->notFullPage[nStart])
                                264                 :            757 :         nStart++;
                                265                 :                : 
                                266                 :                :     /*
                                267                 :                :      * This loop iterates for each page we try from the notFullPage array, and
                                268                 :                :      * will also initialize a GenericXLogState for the fallback case of having
                                269                 :                :      * to allocate a new page.
                                270                 :                :      */
                                271                 :                :     for (;;)
                                272                 :                :     {
 2927 tgl@sss.pgh.pa.us         273                 :UBC           0 :         state = GenericXLogStart(index);
                                274                 :                : 
                                275                 :                :         /* get modifiable copy of metapage */
 2924 tgl@sss.pgh.pa.us         276                 :CBC         758 :         metaPage = GenericXLogRegisterBuffer(state, metaBuffer, 0);
 2927                           277                 :            758 :         metaData = BloomPageGetMeta(metaPage);
                                278                 :                : 
                                279         [ +  + ]:            758 :         if (nStart >= metaData->nEnd)
                                280                 :            113 :             break;              /* no more entries in notFullPage array */
                                281                 :                : 
 2935 teodor@sigaev.ru          282                 :            645 :         blkno = metaData->notFullPage[nStart];
                                283         [ -  + ]:            645 :         Assert(blkno != InvalidBlockNumber);
                                284                 :                : 
                                285                 :            645 :         buffer = ReadBuffer(index, blkno);
                                286                 :            645 :         LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 2924 tgl@sss.pgh.pa.us         287                 :            645 :         page = GenericXLogRegisterBuffer(state, buffer, 0);
                                288                 :                : 
                                289                 :                :         /* Basically same logic as above */
 2801                           290   [ +  -  -  + ]:            645 :         if (PageIsNew(page) || BloomPageIsDeleted(page))
 2801 tgl@sss.pgh.pa.us         291                 :UBC           0 :             BloomInitPage(page, 0);
                                292                 :                : 
 2935 teodor@sigaev.ru          293         [ +  - ]:CBC         645 :         if (BloomPageAddItem(&blstate, page, itup))
                                294                 :                :         {
                                295                 :                :             /* Success!  Apply the changes, clean up, and exit */
                                296                 :            645 :             metaData->nStart = nStart;
                                297                 :            645 :             GenericXLogFinish(state);
                                298                 :            645 :             UnlockReleaseBuffer(buffer);
                                299                 :            645 :             UnlockReleaseBuffer(metaBuffer);
                                300                 :            645 :             MemoryContextSwitchTo(oldCtx);
                                301                 :            645 :             MemoryContextDelete(insertCtx);
                                302                 :            645 :             return false;
                                303                 :                :         }
                                304                 :                : 
                                305                 :                :         /* Didn't fit, must try other pages */
 2927 tgl@sss.pgh.pa.us         306                 :UBC           0 :         GenericXLogAbort(state);
                                307                 :              0 :         UnlockReleaseBuffer(buffer);
 2935 teodor@sigaev.ru          308                 :              0 :         nStart++;
                                309                 :                :     }
                                310                 :                : 
                                311                 :                :     /*
                                312                 :                :      * Didn't find place to insert in notFullPage array.  Allocate new page.
                                313                 :                :      * (XXX is it good to do this while holding ex-lock on the metapage??)
                                314                 :                :      */
 2935 teodor@sigaev.ru          315                 :CBC         113 :     buffer = BloomNewBuffer(index);
                                316                 :                : 
 2924 tgl@sss.pgh.pa.us         317                 :            113 :     page = GenericXLogRegisterBuffer(state, buffer, GENERIC_XLOG_FULL_IMAGE);
 2935 teodor@sigaev.ru          318                 :            113 :     BloomInitPage(page, 0);
                                319                 :                : 
 2933 tgl@sss.pgh.pa.us         320         [ -  + ]:            113 :     if (!BloomPageAddItem(&blstate, page, itup))
                                321                 :                :     {
                                322                 :                :         /* We shouldn't be here since we're inserting to an empty page */
 2933 tgl@sss.pgh.pa.us         323         [ #  # ]:UBC           0 :         elog(ERROR, "could not add new bloom tuple to empty page");
                                324                 :                :     }
                                325                 :                : 
                                326                 :                :     /* Reset notFullPage array to contain just this new page */
 2935 teodor@sigaev.ru          327                 :CBC         113 :     metaData->nStart = 0;
                                328                 :            113 :     metaData->nEnd = 1;
                                329                 :            113 :     metaData->notFullPage[0] = BufferGetBlockNumber(buffer);
                                330                 :                : 
                                331                 :                :     /* Apply the changes, clean up, and exit */
                                332                 :            113 :     GenericXLogFinish(state);
                                333                 :                : 
                                334                 :            113 :     UnlockReleaseBuffer(buffer);
                                335                 :            113 :     UnlockReleaseBuffer(metaBuffer);
                                336                 :                : 
 2927 tgl@sss.pgh.pa.us         337                 :            113 :     MemoryContextSwitchTo(oldCtx);
                                338                 :            113 :     MemoryContextDelete(insertCtx);
                                339                 :                : 
 2935 teodor@sigaev.ru          340                 :            113 :     return false;
                                341                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622