LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapHeapscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 289 302 95.7 %
Date: 2024-04-24 21:11:03 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeBitmapHeapscan.c
       4             :  *    Routines to support bitmapped scans of relations
       5             :  *
       6             :  * NOTE: it is critical that this plan type only be used with MVCC-compliant
       7             :  * snapshots (ie, regular snapshots, not SnapshotAny or one of the other
       8             :  * special snapshots).  The reason is that since index and heap scans are
       9             :  * decoupled, there can be no assurance that the index tuple prompting a
      10             :  * visit to a particular heap TID still exists when the visit is made.
      11             :  * Therefore the tuple might not exist anymore either (which is OK because
      12             :  * heap_fetch will cope) --- but worse, the tuple slot could have been
      13             :  * re-used for a newer tuple.  With an MVCC snapshot the newer tuple is
      14             :  * certain to fail the time qual and so it will not be mistakenly returned,
      15             :  * but with anything else we might return a tuple that doesn't meet the
      16             :  * required index qual conditions.
      17             :  *
      18             :  *
      19             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
      20             :  * Portions Copyright (c) 1994, Regents of the University of California
      21             :  *
      22             :  *
      23             :  * IDENTIFICATION
      24             :  *    src/backend/executor/nodeBitmapHeapscan.c
      25             :  *
      26             :  *-------------------------------------------------------------------------
      27             :  */
      28             : /*
      29             :  * INTERFACE ROUTINES
      30             :  *      ExecBitmapHeapScan          scans a relation using bitmap info
      31             :  *      ExecBitmapHeapNext          workhorse for above
      32             :  *      ExecInitBitmapHeapScan      creates and initializes state info.
      33             :  *      ExecReScanBitmapHeapScan    prepares to rescan the plan.
      34             :  *      ExecEndBitmapHeapScan       releases all storage.
      35             :  */
      36             : #include "postgres.h"
      37             : 
      38             : #include <math.h>
      39             : 
      40             : #include "access/relscan.h"
      41             : #include "access/tableam.h"
      42             : #include "access/visibilitymap.h"
      43             : #include "executor/executor.h"
      44             : #include "executor/nodeBitmapHeapscan.h"
      45             : #include "miscadmin.h"
      46             : #include "pgstat.h"
      47             : #include "storage/bufmgr.h"
      48             : #include "utils/rel.h"
      49             : #include "utils/snapmgr.h"
      50             : #include "utils/spccache.h"
      51             : 
      52             : static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
      53             : static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
      54             : static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
      55             :                                                 BlockNumber blockno);
      56             : static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
      57             : static inline void BitmapPrefetch(BitmapHeapScanState *node,
      58             :                                   TableScanDesc scan);
      59             : static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
      60             : 
      61             : 
      62             : /* ----------------------------------------------------------------
      63             :  *      BitmapHeapNext
      64             :  *
      65             :  *      Retrieve next tuple from the BitmapHeapScan node's currentRelation
      66             :  * ----------------------------------------------------------------
      67             :  */
      68             : static TupleTableSlot *
      69     5768560 : BitmapHeapNext(BitmapHeapScanState *node)
      70             : {
      71             :     ExprContext *econtext;
      72             :     TableScanDesc scan;
      73             :     TIDBitmap  *tbm;
      74     5768560 :     TBMIterator *tbmiterator = NULL;
      75     5768560 :     TBMSharedIterator *shared_tbmiterator = NULL;
      76             :     TBMIterateResult *tbmres;
      77             :     TupleTableSlot *slot;
      78     5768560 :     ParallelBitmapHeapState *pstate = node->pstate;
      79     5768560 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
      80             : 
      81             :     /*
      82             :      * extract necessary information from index scan node
      83             :      */
      84     5768560 :     econtext = node->ss.ps.ps_ExprContext;
      85     5768560 :     slot = node->ss.ss_ScanTupleSlot;
      86     5768560 :     scan = node->ss.ss_currentScanDesc;
      87     5768560 :     tbm = node->tbm;
      88     5768560 :     if (pstate == NULL)
      89     4574218 :         tbmiterator = node->tbmiterator;
      90             :     else
      91     1194342 :         shared_tbmiterator = node->shared_tbmiterator;
      92     5768560 :     tbmres = node->tbmres;
      93             : 
      94             :     /*
      95             :      * If we haven't yet performed the underlying index scan, do it, and begin
      96             :      * the iteration over the bitmap.
      97             :      *
      98             :      * For prefetching, we use *two* iterators, one for the pages we are
      99             :      * actually scanning and another that runs ahead of the first for
     100             :      * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
     101             :      * the prefetch iterator is.  Also, node->prefetch_target tracks the
     102             :      * desired prefetch distance, which starts small and increases up to the
     103             :      * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
     104             :      * a scan that stops after a few tuples because of a LIMIT.
     105             :      */
     106     5768560 :     if (!node->initialized)
     107             :     {
     108       20798 :         if (!pstate)
     109             :         {
     110       20450 :             tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
     111             : 
     112       20450 :             if (!tbm || !IsA(tbm, TIDBitmap))
     113           0 :                 elog(ERROR, "unrecognized result from subplan");
     114             : 
     115       20450 :             node->tbm = tbm;
     116       20450 :             node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
     117       20450 :             node->tbmres = tbmres = NULL;
     118             : 
     119             : #ifdef USE_PREFETCH
     120       20450 :             if (node->prefetch_maximum > 0)
     121             :             {
     122       20450 :                 node->prefetch_iterator = tbm_begin_iterate(tbm);
     123       20450 :                 node->prefetch_pages = 0;
     124       20450 :                 node->prefetch_target = -1;
     125             :             }
     126             : #endif                          /* USE_PREFETCH */
     127             :         }
     128             :         else
     129             :         {
     130             :             /*
     131             :              * The leader will immediately come out of the function, but
     132             :              * others will be blocked until leader populates the TBM and wakes
     133             :              * them up.
     134             :              */
     135         348 :             if (BitmapShouldInitializeSharedState(pstate))
     136             :             {
     137          72 :                 tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
     138          72 :                 if (!tbm || !IsA(tbm, TIDBitmap))
     139           0 :                     elog(ERROR, "unrecognized result from subplan");
     140             : 
     141          72 :                 node->tbm = tbm;
     142             : 
     143             :                 /*
     144             :                  * Prepare to iterate over the TBM. This will return the
     145             :                  * dsa_pointer of the iterator state which will be used by
     146             :                  * multiple processes to iterate jointly.
     147             :                  */
     148          72 :                 pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
     149             : #ifdef USE_PREFETCH
     150          72 :                 if (node->prefetch_maximum > 0)
     151             :                 {
     152          72 :                     pstate->prefetch_iterator =
     153          72 :                         tbm_prepare_shared_iterate(tbm);
     154             : 
     155             :                     /*
     156             :                      * We don't need the mutex here as we haven't yet woke up
     157             :                      * others.
     158             :                      */
     159          72 :                     pstate->prefetch_pages = 0;
     160          72 :                     pstate->prefetch_target = -1;
     161             :                 }
     162             : #endif
     163             : 
     164             :                 /* We have initialized the shared state so wake up others. */
     165          72 :                 BitmapDoneInitializingSharedState(pstate);
     166             :             }
     167             : 
     168             :             /* Allocate a private iterator and attach the shared state to it */
     169         348 :             node->shared_tbmiterator = shared_tbmiterator =
     170         348 :                 tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
     171         348 :             node->tbmres = tbmres = NULL;
     172             : 
     173             : #ifdef USE_PREFETCH
     174         348 :             if (node->prefetch_maximum > 0)
     175             :             {
     176         348 :                 node->shared_prefetch_iterator =
     177         348 :                     tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
     178             :             }
     179             : #endif                          /* USE_PREFETCH */
     180             :         }
     181             : 
     182             :         /*
     183             :          * If this is the first scan of the underlying table, create the table
     184             :          * scan descriptor and begin the scan.
     185             :          */
     186       20798 :         if (!scan)
     187             :         {
     188       16758 :             bool        need_tuples = false;
     189             : 
     190             :             /*
     191             :              * We can potentially skip fetching heap pages if we do not need
     192             :              * any columns of the table, either for checking non-indexable
     193             :              * quals or for returning data.  This test is a bit simplistic, as
     194             :              * it checks the stronger condition that there's no qual or return
     195             :              * tlist at all. But in most cases it's probably not worth working
     196             :              * harder than that.
     197             :              */
     198       29404 :             need_tuples = (node->ss.ps.plan->qual != NIL ||
     199       12646 :                            node->ss.ps.plan->targetlist != NIL);
     200             : 
     201       16758 :             scan = table_beginscan_bm(node->ss.ss_currentRelation,
     202       16758 :                                       node->ss.ps.state->es_snapshot,
     203             :                                       0,
     204             :                                       NULL,
     205             :                                       need_tuples);
     206             : 
     207       16758 :             node->ss.ss_currentScanDesc = scan;
     208             :         }
     209             : 
     210       20798 :         node->initialized = true;
     211             :     }
     212             : 
     213             :     for (;;)
     214      982760 :     {
     215             :         bool        valid_block;
     216             : 
     217     6751320 :         CHECK_FOR_INTERRUPTS();
     218             : 
     219             :         /*
     220             :          * Get next page of results if needed
     221             :          */
     222     6751320 :         if (tbmres == NULL)
     223             :         {
     224      410044 :             if (!pstate)
     225      379588 :                 node->tbmres = tbmres = tbm_iterate(tbmiterator);
     226             :             else
     227       30456 :                 node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
     228      410044 :             if (tbmres == NULL)
     229             :             {
     230             :                 /* no more entries in the bitmap */
     231       20278 :                 break;
     232             :             }
     233             : 
     234      389766 :             BitmapAdjustPrefetchIterator(node, tbmres->blockno);
     235             : 
     236      389766 :             valid_block = table_scan_bitmap_next_block(scan, tbmres);
     237             : 
     238      389760 :             if (tbmres->ntuples >= 0)
     239      232468 :                 node->exact_pages++;
     240             :             else
     241      157292 :                 node->lossy_pages++;
     242             : 
     243      389760 :             if (!valid_block)
     244             :             {
     245             :                 /* AM doesn't think this block is valid, skip */
     246        6008 :                 continue;
     247             :             }
     248             : 
     249             :             /* Adjust the prefetch target */
     250      383752 :             BitmapAdjustPrefetchTarget(node);
     251             :         }
     252             :         else
     253             :         {
     254             :             /*
     255             :              * Continuing in previously obtained page.
     256             :              */
     257             : 
     258             : #ifdef USE_PREFETCH
     259             : 
     260             :             /*
     261             :              * Try to prefetch at least a few pages even before we get to the
     262             :              * second page if we don't stop reading after the first tuple.
     263             :              */
     264     6341276 :             if (!pstate)
     265             :             {
     266     5147276 :                 if (node->prefetch_target < node->prefetch_maximum)
     267       14536 :                     node->prefetch_target++;
     268             :             }
     269     1194000 :             else if (pstate->prefetch_target < node->prefetch_maximum)
     270             :             {
     271             :                 /* take spinlock while updating shared state */
     272        1926 :                 SpinLockAcquire(&pstate->mutex);
     273        1926 :                 if (pstate->prefetch_target < node->prefetch_maximum)
     274        1926 :                     pstate->prefetch_target++;
     275        1926 :                 SpinLockRelease(&pstate->mutex);
     276             :             }
     277             : #endif                          /* USE_PREFETCH */
     278             :         }
     279             : 
     280             :         /*
     281             :          * We issue prefetch requests *after* fetching the current page to try
     282             :          * to avoid having prefetching interfere with the main I/O. Also, this
     283             :          * should happen only when we have determined there is still something
     284             :          * to do on the current page, else we may uselessly prefetch the same
     285             :          * page we are just about to request for real.
     286             :          */
     287     6725028 :         BitmapPrefetch(node, scan);
     288             : 
     289             :         /*
     290             :          * Attempt to fetch tuple from AM.
     291             :          */
     292     6725028 :         if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
     293             :         {
     294             :             /* nothing more to look at on this page */
     295      389246 :             node->tbmres = tbmres = NULL;
     296      389246 :             continue;
     297             :         }
     298             : 
     299             :         /*
     300             :          * If we are using lossy info, we have to recheck the qual conditions
     301             :          * at every tuple.
     302             :          */
     303     6335782 :         if (tbmres->recheck)
     304             :         {
     305     3124632 :             econtext->ecxt_scantuple = slot;
     306     3124632 :             if (!ExecQualAndReset(node->bitmapqualorig, econtext))
     307             :             {
     308             :                 /* Fails recheck, so drop it and loop back for another */
     309      587506 :                 InstrCountFiltered2(node, 1);
     310      587506 :                 ExecClearTuple(slot);
     311      587506 :                 continue;
     312             :             }
     313             :         }
     314             : 
     315             :         /* OK to return this tuple */
     316     5748276 :         return slot;
     317             :     }
     318             : 
     319             :     /*
     320             :      * if we get here it means we are at the end of the scan..
     321             :      */
     322       20278 :     return ExecClearTuple(slot);
     323             : }
     324             : 
     325             : /*
     326             :  *  BitmapDoneInitializingSharedState - Shared state is initialized
     327             :  *
     328             :  *  By this time the leader has already populated the TBM and initialized the
     329             :  *  shared state so wake up other processes.
     330             :  */
     331             : static inline void
     332          72 : BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
     333             : {
     334          72 :     SpinLockAcquire(&pstate->mutex);
     335          72 :     pstate->state = BM_FINISHED;
     336          72 :     SpinLockRelease(&pstate->mutex);
     337          72 :     ConditionVariableBroadcast(&pstate->cv);
     338          72 : }
     339             : 
     340             : /*
     341             :  *  BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
     342             :  */
     343             : static inline void
     344      389766 : BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
     345             :                              BlockNumber blockno)
     346             : {
     347             : #ifdef USE_PREFETCH
     348      389766 :     ParallelBitmapHeapState *pstate = node->pstate;
     349             : 
     350      389766 :     if (pstate == NULL)
     351             :     {
     352      359658 :         TBMIterator *prefetch_iterator = node->prefetch_iterator;
     353             : 
     354      359658 :         if (node->prefetch_pages > 0)
     355             :         {
     356             :             /* The main iterator has closed the distance by one page */
     357      344394 :             node->prefetch_pages--;
     358             :         }
     359       15264 :         else if (prefetch_iterator)
     360             :         {
     361             :             /* Do not let the prefetch iterator get behind the main one */
     362       15264 :             TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
     363             : 
     364       15264 :             if (tbmpre == NULL || tbmpre->blockno != blockno)
     365           0 :                 elog(ERROR, "prefetch and main iterators are out of sync");
     366             :         }
     367      359658 :         return;
     368             :     }
     369             : 
     370       30108 :     if (node->prefetch_maximum > 0)
     371             :     {
     372       30108 :         TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
     373             : 
     374       30108 :         SpinLockAcquire(&pstate->mutex);
     375       30108 :         if (pstate->prefetch_pages > 0)
     376             :         {
     377       30036 :             pstate->prefetch_pages--;
     378       30036 :             SpinLockRelease(&pstate->mutex);
     379             :         }
     380             :         else
     381             :         {
     382             :             /* Release the mutex before iterating */
     383          72 :             SpinLockRelease(&pstate->mutex);
     384             : 
     385             :             /*
     386             :              * In case of shared mode, we can not ensure that the current
     387             :              * blockno of the main iterator and that of the prefetch iterator
     388             :              * are same.  It's possible that whatever blockno we are
     389             :              * prefetching will be processed by another process.  Therefore,
     390             :              * we don't validate the blockno here as we do in non-parallel
     391             :              * case.
     392             :              */
     393          72 :             if (prefetch_iterator)
     394          72 :                 tbm_shared_iterate(prefetch_iterator);
     395             :         }
     396             :     }
     397             : #endif                          /* USE_PREFETCH */
     398             : }
     399             : 
     400             : /*
     401             :  * BitmapAdjustPrefetchTarget - Adjust the prefetch target
     402             :  *
     403             :  * Increase prefetch target if it's not yet at the max.  Note that
     404             :  * we will increase it to zero after fetching the very first
     405             :  * page/tuple, then to one after the second tuple is fetched, then
     406             :  * it doubles as later pages are fetched.
     407             :  */
     408             : static inline void
     409      383752 : BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
     410             : {
     411             : #ifdef USE_PREFETCH
     412      383752 :     ParallelBitmapHeapState *pstate = node->pstate;
     413             : 
     414      383752 :     if (pstate == NULL)
     415             :     {
     416      353644 :         if (node->prefetch_target >= node->prefetch_maximum)
     417             :              /* don't increase any further */ ;
     418       14830 :         else if (node->prefetch_target >= node->prefetch_maximum / 2)
     419         232 :             node->prefetch_target = node->prefetch_maximum;
     420       14598 :         else if (node->prefetch_target > 0)
     421           0 :             node->prefetch_target *= 2;
     422             :         else
     423       14598 :             node->prefetch_target++;
     424      353644 :         return;
     425             :     }
     426             : 
     427             :     /* Do an unlocked check first to save spinlock acquisitions. */
     428       30108 :     if (pstate->prefetch_target < node->prefetch_maximum)
     429             :     {
     430         132 :         SpinLockAcquire(&pstate->mutex);
     431         132 :         if (pstate->prefetch_target >= node->prefetch_maximum)
     432             :              /* don't increase any further */ ;
     433         132 :         else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
     434          60 :             pstate->prefetch_target = node->prefetch_maximum;
     435          72 :         else if (pstate->prefetch_target > 0)
     436           0 :             pstate->prefetch_target *= 2;
     437             :         else
     438          72 :             pstate->prefetch_target++;
     439         132 :         SpinLockRelease(&pstate->mutex);
     440             :     }
     441             : #endif                          /* USE_PREFETCH */
     442             : }
     443             : 
     444             : /*
     445             :  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
     446             :  */
     447             : static inline void
     448     6725028 : BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
     449             : {
     450             : #ifdef USE_PREFETCH
     451     6725028 :     ParallelBitmapHeapState *pstate = node->pstate;
     452             : 
     453     6725028 :     if (pstate == NULL)
     454             :     {
     455     5500920 :         TBMIterator *prefetch_iterator = node->prefetch_iterator;
     456             : 
     457     5500920 :         if (prefetch_iterator)
     458             :         {
     459     5749904 :             while (node->prefetch_pages < node->prefetch_target)
     460             :             {
     461      358772 :                 TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
     462             :                 bool        skip_fetch;
     463             : 
     464      358772 :                 if (tbmpre == NULL)
     465             :                 {
     466             :                     /* No more pages to prefetch */
     467       14378 :                     tbm_end_iterate(prefetch_iterator);
     468       14378 :                     node->prefetch_iterator = NULL;
     469       14378 :                     break;
     470             :                 }
     471      344394 :                 node->prefetch_pages++;
     472             : 
     473             :                 /*
     474             :                  * If we expect not to have to actually read this heap page,
     475             :                  * skip this prefetch call, but continue to run the prefetch
     476             :                  * logic normally.  (Would it be better not to increment
     477             :                  * prefetch_pages?)
     478             :                  */
     479      755274 :                 skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
     480      376130 :                               !tbmpre->recheck &&
     481       31736 :                               VM_ALL_VISIBLE(node->ss.ss_currentRelation,
     482             :                                              tbmpre->blockno,
     483             :                                              &node->pvmbuffer));
     484             : 
     485      344394 :                 if (!skip_fetch)
     486      344324 :                     PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
     487             :             }
     488             :         }
     489             : 
     490     5500920 :         return;
     491             :     }
     492             : 
     493     1224108 :     if (pstate->prefetch_pages < pstate->prefetch_target)
     494             :     {
     495      138846 :         TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
     496             : 
     497      138846 :         if (prefetch_iterator)
     498             :         {
     499             :             while (1)
     500       30036 :             {
     501             :                 TBMIterateResult *tbmpre;
     502       58764 :                 bool        do_prefetch = false;
     503             :                 bool        skip_fetch;
     504             : 
     505             :                 /*
     506             :                  * Recheck under the mutex. If some other process has already
     507             :                  * done enough prefetching then we need not to do anything.
     508             :                  */
     509       58764 :                 SpinLockAcquire(&pstate->mutex);
     510       58764 :                 if (pstate->prefetch_pages < pstate->prefetch_target)
     511             :                 {
     512       30108 :                     pstate->prefetch_pages++;
     513       30108 :                     do_prefetch = true;
     514             :                 }
     515       58764 :                 SpinLockRelease(&pstate->mutex);
     516             : 
     517       58764 :                 if (!do_prefetch)
     518       28656 :                     return;
     519             : 
     520       30108 :                 tbmpre = tbm_shared_iterate(prefetch_iterator);
     521       30108 :                 if (tbmpre == NULL)
     522             :                 {
     523             :                     /* No more pages to prefetch */
     524          72 :                     tbm_end_shared_iterate(prefetch_iterator);
     525          72 :                     node->shared_prefetch_iterator = NULL;
     526          72 :                     break;
     527             :                 }
     528             : 
     529             :                 /* As above, skip prefetch if we expect not to need page */
     530       88116 :                 skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
     531       54984 :                               !tbmpre->recheck &&
     532       24948 :                               VM_ALL_VISIBLE(node->ss.ss_currentRelation,
     533             :                                              tbmpre->blockno,
     534             :                                              &node->pvmbuffer));
     535             : 
     536       30036 :                 if (!skip_fetch)
     537        9396 :                     PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
     538             :             }
     539             :         }
     540             :     }
     541             : #endif                          /* USE_PREFETCH */
     542             : }
     543             : 
     544             : /*
     545             :  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
     546             :  */
     547             : static bool
     548           0 : BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
     549             : {
     550             :     ExprContext *econtext;
     551             : 
     552             :     /*
     553             :      * extract necessary information from index scan node
     554             :      */
     555           0 :     econtext = node->ss.ps.ps_ExprContext;
     556             : 
     557             :     /* Does the tuple meet the original qual conditions? */
     558           0 :     econtext->ecxt_scantuple = slot;
     559           0 :     return ExecQualAndReset(node->bitmapqualorig, econtext);
     560             : }
     561             : 
     562             : /* ----------------------------------------------------------------
     563             :  *      ExecBitmapHeapScan(node)
     564             :  * ----------------------------------------------------------------
     565             :  */
     566             : static TupleTableSlot *
     567     5516196 : ExecBitmapHeapScan(PlanState *pstate)
     568             : {
     569     5516196 :     BitmapHeapScanState *node = castNode(BitmapHeapScanState, pstate);
     570             : 
     571     5516196 :     return ExecScan(&node->ss,
     572             :                     (ExecScanAccessMtd) BitmapHeapNext,
     573             :                     (ExecScanRecheckMtd) BitmapHeapRecheck);
     574             : }
     575             : 
     576             : /* ----------------------------------------------------------------
     577             :  *      ExecReScanBitmapHeapScan(node)
     578             :  * ----------------------------------------------------------------
     579             :  */
     580             : void
     581        6752 : ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
     582             : {
     583        6752 :     PlanState  *outerPlan = outerPlanState(node);
     584             : 
     585             :     /* rescan to release any page pin */
     586        6752 :     if (node->ss.ss_currentScanDesc)
     587        4040 :         table_rescan(node->ss.ss_currentScanDesc, NULL);
     588             : 
     589             :     /* release bitmaps and buffers if any */
     590        6752 :     if (node->tbmiterator)
     591        3986 :         tbm_end_iterate(node->tbmiterator);
     592        6752 :     if (node->prefetch_iterator)
     593        1354 :         tbm_end_iterate(node->prefetch_iterator);
     594        6752 :     if (node->shared_tbmiterator)
     595          54 :         tbm_end_shared_iterate(node->shared_tbmiterator);
     596        6752 :     if (node->shared_prefetch_iterator)
     597           0 :         tbm_end_shared_iterate(node->shared_prefetch_iterator);
     598        6752 :     if (node->tbm)
     599        4040 :         tbm_free(node->tbm);
     600        6752 :     if (node->pvmbuffer != InvalidBuffer)
     601          54 :         ReleaseBuffer(node->pvmbuffer);
     602        6752 :     node->tbm = NULL;
     603        6752 :     node->tbmiterator = NULL;
     604        6752 :     node->tbmres = NULL;
     605        6752 :     node->prefetch_iterator = NULL;
     606        6752 :     node->initialized = false;
     607        6752 :     node->shared_tbmiterator = NULL;
     608        6752 :     node->shared_prefetch_iterator = NULL;
     609        6752 :     node->pvmbuffer = InvalidBuffer;
     610             : 
     611        6752 :     ExecScanReScan(&node->ss);
     612             : 
     613             :     /*
     614             :      * if chgParam of subnode is not null then plan will be re-scanned by
     615             :      * first ExecProcNode.
     616             :      */
     617        6752 :     if (outerPlan->chgParam == NULL)
     618         192 :         ExecReScan(outerPlan);
     619        6752 : }
     620             : 
     621             : /* ----------------------------------------------------------------
     622             :  *      ExecEndBitmapHeapScan
     623             :  * ----------------------------------------------------------------
     624             :  */
     625             : void
     626       21238 : ExecEndBitmapHeapScan(BitmapHeapScanState *node)
     627             : {
     628             :     TableScanDesc scanDesc;
     629             : 
     630             :     /*
     631             :      * extract information from the node
     632             :      */
     633       21238 :     scanDesc = node->ss.ss_currentScanDesc;
     634             : 
     635             :     /*
     636             :      * close down subplans
     637             :      */
     638       21238 :     ExecEndNode(outerPlanState(node));
     639             : 
     640             :     /*
     641             :      * release bitmaps and buffers if any
     642             :      */
     643       21238 :     if (node->tbmiterator)
     644       16368 :         tbm_end_iterate(node->tbmiterator);
     645       21238 :     if (node->prefetch_iterator)
     646        4706 :         tbm_end_iterate(node->prefetch_iterator);
     647       21238 :     if (node->tbm)
     648       16386 :         tbm_free(node->tbm);
     649       21238 :     if (node->shared_tbmiterator)
     650         294 :         tbm_end_shared_iterate(node->shared_tbmiterator);
     651       21238 :     if (node->shared_prefetch_iterator)
     652         276 :         tbm_end_shared_iterate(node->shared_prefetch_iterator);
     653       21238 :     if (node->pvmbuffer != InvalidBuffer)
     654          24 :         ReleaseBuffer(node->pvmbuffer);
     655             : 
     656             :     /*
     657             :      * close heap scan
     658             :      */
     659       21238 :     if (scanDesc)
     660       16662 :         table_endscan(scanDesc);
     661             : 
     662       21238 : }
     663             : 
     664             : /* ----------------------------------------------------------------
     665             :  *      ExecInitBitmapHeapScan
     666             :  *
     667             :  *      Initializes the scan's state information.
     668             :  * ----------------------------------------------------------------
     669             :  */
     670             : BitmapHeapScanState *
     671       21334 : ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
     672             : {
     673             :     BitmapHeapScanState *scanstate;
     674             :     Relation    currentRelation;
     675             : 
     676             :     /* check for unsupported flags */
     677             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     678             : 
     679             :     /*
     680             :      * Assert caller didn't ask for an unsafe snapshot --- see comments at
     681             :      * head of file.
     682             :      */
     683             :     Assert(IsMVCCSnapshot(estate->es_snapshot));
     684             : 
     685             :     /*
     686             :      * create state structure
     687             :      */
     688       21334 :     scanstate = makeNode(BitmapHeapScanState);
     689       21334 :     scanstate->ss.ps.plan = (Plan *) node;
     690       21334 :     scanstate->ss.ps.state = estate;
     691       21334 :     scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
     692             : 
     693       21334 :     scanstate->tbm = NULL;
     694       21334 :     scanstate->tbmiterator = NULL;
     695       21334 :     scanstate->tbmres = NULL;
     696       21334 :     scanstate->pvmbuffer = InvalidBuffer;
     697       21334 :     scanstate->exact_pages = 0;
     698       21334 :     scanstate->lossy_pages = 0;
     699       21334 :     scanstate->prefetch_iterator = NULL;
     700       21334 :     scanstate->prefetch_pages = 0;
     701       21334 :     scanstate->prefetch_target = 0;
     702       21334 :     scanstate->initialized = false;
     703       21334 :     scanstate->shared_tbmiterator = NULL;
     704       21334 :     scanstate->shared_prefetch_iterator = NULL;
     705       21334 :     scanstate->pstate = NULL;
     706             : 
     707             :     /*
     708             :      * Miscellaneous initialization
     709             :      *
     710             :      * create expression context for node
     711             :      */
     712       21334 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     713             : 
     714             :     /*
     715             :      * open the scan relation
     716             :      */
     717       21334 :     currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
     718             : 
     719             :     /*
     720             :      * initialize child nodes
     721             :      */
     722       21334 :     outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
     723             : 
     724             :     /*
     725             :      * get the scan type from the relation descriptor.
     726             :      */
     727       21334 :     ExecInitScanTupleSlot(estate, &scanstate->ss,
     728             :                           RelationGetDescr(currentRelation),
     729             :                           table_slot_callbacks(currentRelation));
     730             : 
     731             :     /*
     732             :      * Initialize result type and projection.
     733             :      */
     734       21334 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     735       21334 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     736             : 
     737             :     /*
     738             :      * initialize child expressions
     739             :      */
     740       21334 :     scanstate->ss.ps.qual =
     741       21334 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     742       21334 :     scanstate->bitmapqualorig =
     743       21334 :         ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
     744             : 
     745             :     /*
     746             :      * Maximum number of prefetches for the tablespace if configured,
     747             :      * otherwise the current value of the effective_io_concurrency GUC.
     748             :      */
     749       21334 :     scanstate->prefetch_maximum =
     750       21334 :         get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
     751             : 
     752       21334 :     scanstate->ss.ss_currentRelation = currentRelation;
     753             : 
     754             :     /*
     755             :      * all done.
     756             :      */
     757       21334 :     return scanstate;
     758             : }
     759             : 
     760             : /*----------------
     761             :  *      BitmapShouldInitializeSharedState
     762             :  *
     763             :  *      The first process to come here and see the state to the BM_INITIAL
     764             :  *      will become the leader for the parallel bitmap scan and will be
     765             :  *      responsible for populating the TIDBitmap.  The other processes will
     766             :  *      be blocked by the condition variable until the leader wakes them up.
     767             :  * ---------------
     768             :  */
     769             : static bool
     770         348 : BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
     771             : {
     772             :     SharedBitmapState state;
     773             : 
     774             :     while (1)
     775             :     {
     776         348 :         SpinLockAcquire(&pstate->mutex);
     777         348 :         state = pstate->state;
     778         348 :         if (pstate->state == BM_INITIAL)
     779          72 :             pstate->state = BM_INPROGRESS;
     780         348 :         SpinLockRelease(&pstate->mutex);
     781             : 
     782             :         /* Exit if bitmap is done, or if we're the leader. */
     783         348 :         if (state != BM_INPROGRESS)
     784         348 :             break;
     785             : 
     786             :         /* Wait for the leader to wake us up. */
     787           0 :         ConditionVariableSleep(&pstate->cv, WAIT_EVENT_PARALLEL_BITMAP_SCAN);
     788             :     }
     789             : 
     790         348 :     ConditionVariableCancelSleep();
     791             : 
     792         348 :     return (state == BM_INITIAL);
     793             : }
     794             : 
     795             : /* ----------------------------------------------------------------
     796             :  *      ExecBitmapHeapEstimate
     797             :  *
     798             :  *      Compute the amount of space we'll need in the parallel
     799             :  *      query DSM, and inform pcxt->estimator about our needs.
     800             :  * ----------------------------------------------------------------
     801             :  */
     802             : void
     803          18 : ExecBitmapHeapEstimate(BitmapHeapScanState *node,
     804             :                        ParallelContext *pcxt)
     805             : {
     806          18 :     shm_toc_estimate_chunk(&pcxt->estimator, sizeof(ParallelBitmapHeapState));
     807          18 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
     808          18 : }
     809             : 
     810             : /* ----------------------------------------------------------------
     811             :  *      ExecBitmapHeapInitializeDSM
     812             :  *
     813             :  *      Set up a parallel bitmap heap scan descriptor.
     814             :  * ----------------------------------------------------------------
     815             :  */
     816             : void
     817          18 : ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
     818             :                             ParallelContext *pcxt)
     819             : {
     820             :     ParallelBitmapHeapState *pstate;
     821          18 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
     822             : 
     823             :     /* If there's no DSA, there are no workers; initialize nothing. */
     824          18 :     if (dsa == NULL)
     825           0 :         return;
     826             : 
     827          18 :     pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
     828             : 
     829          18 :     pstate->tbmiterator = 0;
     830          18 :     pstate->prefetch_iterator = 0;
     831             : 
     832             :     /* Initialize the mutex */
     833          18 :     SpinLockInit(&pstate->mutex);
     834          18 :     pstate->prefetch_pages = 0;
     835          18 :     pstate->prefetch_target = 0;
     836          18 :     pstate->state = BM_INITIAL;
     837             : 
     838          18 :     ConditionVariableInit(&pstate->cv);
     839             : 
     840          18 :     shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
     841          18 :     node->pstate = pstate;
     842             : }
     843             : 
     844             : /* ----------------------------------------------------------------
     845             :  *      ExecBitmapHeapReInitializeDSM
     846             :  *
     847             :  *      Reset shared state before beginning a fresh scan.
     848             :  * ----------------------------------------------------------------
     849             :  */
     850             : void
     851          54 : ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
     852             :                               ParallelContext *pcxt)
     853             : {
     854          54 :     ParallelBitmapHeapState *pstate = node->pstate;
     855          54 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
     856             : 
     857             :     /* If there's no DSA, there are no workers; do nothing. */
     858          54 :     if (dsa == NULL)
     859           0 :         return;
     860             : 
     861          54 :     pstate->state = BM_INITIAL;
     862             : 
     863          54 :     if (DsaPointerIsValid(pstate->tbmiterator))
     864          54 :         tbm_free_shared_area(dsa, pstate->tbmiterator);
     865             : 
     866          54 :     if (DsaPointerIsValid(pstate->prefetch_iterator))
     867          54 :         tbm_free_shared_area(dsa, pstate->prefetch_iterator);
     868             : 
     869          54 :     pstate->tbmiterator = InvalidDsaPointer;
     870          54 :     pstate->prefetch_iterator = InvalidDsaPointer;
     871             : }
     872             : 
     873             : /* ----------------------------------------------------------------
     874             :  *      ExecBitmapHeapInitializeWorker
     875             :  *
     876             :  *      Copy relevant information from TOC into planstate.
     877             :  * ----------------------------------------------------------------
     878             :  */
     879             : void
     880         276 : ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
     881             :                                ParallelWorkerContext *pwcxt)
     882             : {
     883             :     ParallelBitmapHeapState *pstate;
     884             : 
     885             :     Assert(node->ss.ps.state->es_query_dsa != NULL);
     886             : 
     887         276 :     pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
     888         276 :     node->pstate = pstate;
     889         276 : }

Generated by: LCOV version 1.14