LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapHeapscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 312 326 95.7 %
Date: 2019-06-19 14:06:47 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-2019, 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/transam.h"
      43             : #include "access/visibilitymap.h"
      44             : #include "executor/execdebug.h"
      45             : #include "executor/nodeBitmapHeapscan.h"
      46             : #include "miscadmin.h"
      47             : #include "pgstat.h"
      48             : #include "storage/bufmgr.h"
      49             : #include "storage/predicate.h"
      50             : #include "utils/memutils.h"
      51             : #include "utils/rel.h"
      52             : #include "utils/spccache.h"
      53             : #include "utils/snapmgr.h"
      54             : 
      55             : 
      56             : static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
      57             : static inline void BitmapDoneInitializingSharedState(
      58             :                                                      ParallelBitmapHeapState *pstate);
      59             : static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
      60             :                                                 TBMIterateResult *tbmres);
      61             : static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
      62             : static inline void BitmapPrefetch(BitmapHeapScanState *node,
      63             :                                   TableScanDesc scan);
      64             : static bool BitmapShouldInitializeSharedState(
      65             :                                               ParallelBitmapHeapState *pstate);
      66             : 
      67             : 
      68             : /* ----------------------------------------------------------------
      69             :  *      BitmapHeapNext
      70             :  *
      71             :  *      Retrieve next tuple from the BitmapHeapScan node's currentRelation
      72             :  * ----------------------------------------------------------------
      73             :  */
      74             : static TupleTableSlot *
      75     1983516 : BitmapHeapNext(BitmapHeapScanState *node)
      76             : {
      77             :     ExprContext *econtext;
      78             :     TableScanDesc scan;
      79             :     TIDBitmap  *tbm;
      80     1983516 :     TBMIterator *tbmiterator = NULL;
      81     1983516 :     TBMSharedIterator *shared_tbmiterator = NULL;
      82             :     TBMIterateResult *tbmres;
      83             :     TupleTableSlot *slot;
      84     1983516 :     ParallelBitmapHeapState *pstate = node->pstate;
      85     1983516 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
      86             : 
      87             :     /*
      88             :      * extract necessary information from index scan node
      89             :      */
      90     1983516 :     econtext = node->ss.ps.ps_ExprContext;
      91     1983516 :     slot = node->ss.ss_ScanTupleSlot;
      92     1983516 :     scan = node->ss.ss_currentScanDesc;
      93     1983516 :     tbm = node->tbm;
      94     1983516 :     if (pstate == NULL)
      95     1191300 :         tbmiterator = node->tbmiterator;
      96             :     else
      97      792216 :         shared_tbmiterator = node->shared_tbmiterator;
      98     1983516 :     tbmres = node->tbmres;
      99             : 
     100             :     /*
     101             :      * If we haven't yet performed the underlying index scan, do it, and begin
     102             :      * the iteration over the bitmap.
     103             :      *
     104             :      * For prefetching, we use *two* iterators, one for the pages we are
     105             :      * actually scanning and another that runs ahead of the first for
     106             :      * prefetching.  node->prefetch_pages tracks exactly how many pages ahead
     107             :      * the prefetch iterator is.  Also, node->prefetch_target tracks the
     108             :      * desired prefetch distance, which starts small and increases up to the
     109             :      * node->prefetch_maximum.  This is to avoid doing a lot of prefetching in
     110             :      * a scan that stops after a few tuples because of a LIMIT.
     111             :      */
     112     1983516 :     if (!node->initialized)
     113             :     {
     114       13930 :         if (!pstate)
     115             :         {
     116       13710 :             tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
     117             : 
     118       13710 :             if (!tbm || !IsA(tbm, TIDBitmap))
     119           0 :                 elog(ERROR, "unrecognized result from subplan");
     120             : 
     121       13710 :             node->tbm = tbm;
     122       13710 :             node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
     123       13710 :             node->tbmres = tbmres = NULL;
     124             : 
     125             : #ifdef USE_PREFETCH
     126       13710 :             if (node->prefetch_maximum > 0)
     127             :             {
     128       13710 :                 node->prefetch_iterator = tbm_begin_iterate(tbm);
     129       13710 :                 node->prefetch_pages = 0;
     130       13710 :                 node->prefetch_target = -1;
     131             :             }
     132             : #endif                          /* USE_PREFETCH */
     133             :         }
     134             :         else
     135             :         {
     136             :             /*
     137             :              * The leader will immediately come out of the function, but
     138             :              * others will be blocked until leader populates the TBM and wakes
     139             :              * them up.
     140             :              */
     141         220 :             if (BitmapShouldInitializeSharedState(pstate))
     142             :             {
     143          44 :                 tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
     144          44 :                 if (!tbm || !IsA(tbm, TIDBitmap))
     145           0 :                     elog(ERROR, "unrecognized result from subplan");
     146             : 
     147          44 :                 node->tbm = tbm;
     148             : 
     149             :                 /*
     150             :                  * Prepare to iterate over the TBM. This will return the
     151             :                  * dsa_pointer of the iterator state which will be used by
     152             :                  * multiple processes to iterate jointly.
     153             :                  */
     154          44 :                 pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
     155             : #ifdef USE_PREFETCH
     156          44 :                 if (node->prefetch_maximum > 0)
     157             :                 {
     158          44 :                     pstate->prefetch_iterator =
     159          44 :                         tbm_prepare_shared_iterate(tbm);
     160             : 
     161             :                     /*
     162             :                      * We don't need the mutex here as we haven't yet woke up
     163             :                      * others.
     164             :                      */
     165          44 :                     pstate->prefetch_pages = 0;
     166          44 :                     pstate->prefetch_target = -1;
     167             :                 }
     168             : #endif
     169             : 
     170             :                 /* We have initialized the shared state so wake up others. */
     171          44 :                 BitmapDoneInitializingSharedState(pstate);
     172             :             }
     173             : 
     174             :             /* Allocate a private iterator and attach the shared state to it */
     175         220 :             node->shared_tbmiterator = shared_tbmiterator =
     176         220 :                 tbm_attach_shared_iterate(dsa, pstate->tbmiterator);
     177         220 :             node->tbmres = tbmres = NULL;
     178             : 
     179             : #ifdef USE_PREFETCH
     180         220 :             if (node->prefetch_maximum > 0)
     181             :             {
     182         220 :                 node->shared_prefetch_iterator =
     183         220 :                     tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator);
     184             :             }
     185             : #endif                          /* USE_PREFETCH */
     186             :         }
     187       13930 :         node->initialized = true;
     188             :     }
     189             : 
     190             :     for (;;)
     191      406868 :     {
     192             :         bool        skip_fetch;
     193             : 
     194     2390384 :         CHECK_FOR_INTERRUPTS();
     195             : 
     196             :         /*
     197             :          * Get next page of results if needed
     198             :          */
     199     2390384 :         if (tbmres == NULL)
     200             :         {
     201      147736 :             if (!pstate)
     202      128776 :                 node->tbmres = tbmres = tbm_iterate(tbmiterator);
     203             :             else
     204       18960 :                 node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
     205      147736 :             if (tbmres == NULL)
     206             :             {
     207             :                 /* no more entries in the bitmap */
     208       13778 :                 break;
     209             :             }
     210             : 
     211      133958 :             BitmapAdjustPrefetchIterator(node, tbmres);
     212             : 
     213             :             /*
     214             :              * We can skip fetching the heap page if we don't need any fields
     215             :              * from the heap, and the bitmap entries don't need rechecking,
     216             :              * and all tuples on the page are visible to our transaction.
     217             :              *
     218             :              * XXX: It's a layering violation that we do these checks above
     219             :              * tableam, they should probably moved below it at some point.
     220             :              */
     221      312344 :             skip_fetch = (node->can_skip_fetch &&
     222      168266 :                           !tbmres->recheck &&
     223       34308 :                           VM_ALL_VISIBLE(node->ss.ss_currentRelation,
     224             :                                          tbmres->blockno,
     225             :                                          &node->vmbuffer));
     226             : 
     227      133958 :             if (skip_fetch)
     228             :             {
     229             :                 /* can't be lossy in the skip_fetch case */
     230             :                 Assert(tbmres->ntuples >= 0);
     231             : 
     232             :                 /*
     233             :                  * The number of tuples on this page is put into
     234             :                  * node->return_empty_tuples.
     235             :                  */
     236       14516 :                 node->return_empty_tuples = tbmres->ntuples;
     237             :             }
     238      119442 :             else if (!table_scan_bitmap_next_block(scan, tbmres))
     239             :             {
     240             :                 /* AM doesn't think this block is valid, skip */
     241        1508 :                 continue;
     242             :             }
     243             : 
     244      132444 :             if (tbmres->ntuples >= 0)
     245       52328 :                 node->exact_pages++;
     246             :             else
     247       80116 :                 node->lossy_pages++;
     248             : 
     249             :             /* Adjust the prefetch target */
     250      132444 :             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     2242648 :             if (!pstate)
     265             :             {
     266     1464448 :                 if (node->prefetch_target < node->prefetch_maximum)
     267        8022 :                     node->prefetch_target++;
     268             :             }
     269      778200 :             else if (pstate->prefetch_target < node->prefetch_maximum)
     270             :             {
     271             :                 /* take spinlock while updating shared state */
     272        3856 :                 SpinLockAcquire(&pstate->mutex);
     273        3856 :                 if (pstate->prefetch_target < node->prefetch_maximum)
     274        3856 :                     pstate->prefetch_target++;
     275        3856 :                 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             :          * XXX: It's a layering violation that we do these checks above
     288             :          * tableam, they should probably moved below it at some point.
     289             :          */
     290     2375092 :         BitmapPrefetch(node, scan);
     291             : 
     292     2375092 :         if (node->return_empty_tuples > 0)
     293             :         {
     294             :             /*
     295             :              * If we don't have to fetch the tuple, just return nulls.
     296             :              */
     297      398004 :             ExecStoreAllNullTuple(slot);
     298             : 
     299      398004 :             if (--node->return_empty_tuples == 0)
     300             :             {
     301             :                 /* no more tuples to return in the next round */
     302       14516 :                 node->tbmres = tbmres = NULL;
     303             :             }
     304             :         }
     305             :         else
     306             :         {
     307             :             /*
     308             :              * Attempt to fetch tuple from AM.
     309             :              */
     310     1977088 :             if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
     311             :             {
     312             :                 /* nothing more to look at on this page */
     313      119290 :                 node->tbmres = tbmres = NULL;
     314      119290 :                 continue;
     315             :             }
     316             : 
     317             :             /*
     318             :              * If we are using lossy info, we have to recheck the qual
     319             :              * conditions at every tuple.
     320             :              */
     321     1857798 :             if (tbmres->recheck)
     322             :             {
     323      606602 :                 econtext->ecxt_scantuple = slot;
     324      606602 :                 if (!ExecQualAndReset(node->bitmapqualorig, econtext))
     325             :                 {
     326             :                     /* Fails recheck, so drop it and loop back for another */
     327      286070 :                     InstrCountFiltered2(node, 1);
     328      286070 :                     ExecClearTuple(slot);
     329      286070 :                     continue;
     330             :                 }
     331             :             }
     332             :         }
     333             : 
     334             :         /* OK to return this tuple */
     335     1969732 :         return slot;
     336             :     }
     337             : 
     338             :     /*
     339             :      * if we get here it means we are at the end of the scan..
     340             :      */
     341       13778 :     return ExecClearTuple(slot);
     342             : }
     343             : 
     344             : /*
     345             :  *  BitmapDoneInitializingSharedState - Shared state is initialized
     346             :  *
     347             :  *  By this time the leader has already populated the TBM and initialized the
     348             :  *  shared state so wake up other processes.
     349             :  */
     350             : static inline void
     351          44 : BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
     352             : {
     353          44 :     SpinLockAcquire(&pstate->mutex);
     354          44 :     pstate->state = BM_FINISHED;
     355          44 :     SpinLockRelease(&pstate->mutex);
     356          44 :     ConditionVariableBroadcast(&pstate->cv);
     357          44 : }
     358             : 
     359             : /*
     360             :  *  BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
     361             :  */
     362             : static inline void
     363      133958 : BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
     364             :                              TBMIterateResult *tbmres)
     365             : {
     366             : #ifdef USE_PREFETCH
     367      133958 :     ParallelBitmapHeapState *pstate = node->pstate;
     368             : 
     369      133958 :     if (pstate == NULL)
     370             :     {
     371      115218 :         TBMIterator *prefetch_iterator = node->prefetch_iterator;
     372             : 
     373      115218 :         if (node->prefetch_pages > 0)
     374             :         {
     375             :             /* The main iterator has closed the distance by one page */
     376      106976 :             node->prefetch_pages--;
     377             :         }
     378        8242 :         else if (prefetch_iterator)
     379             :         {
     380             :             /* Do not let the prefetch iterator get behind the main one */
     381        8242 :             TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
     382             : 
     383        8242 :             if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
     384           0 :                 elog(ERROR, "prefetch and main iterators are out of sync");
     385             :         }
     386      115218 :         return;
     387             :     }
     388             : 
     389       18740 :     if (node->prefetch_maximum > 0)
     390             :     {
     391       18740 :         TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
     392             : 
     393       18740 :         SpinLockAcquire(&pstate->mutex);
     394       18740 :         if (pstate->prefetch_pages > 0)
     395             :         {
     396       18696 :             pstate->prefetch_pages--;
     397       18696 :             SpinLockRelease(&pstate->mutex);
     398             :         }
     399             :         else
     400             :         {
     401             :             /* Release the mutex before iterating */
     402          44 :             SpinLockRelease(&pstate->mutex);
     403             : 
     404             :             /*
     405             :              * In case of shared mode, we can not ensure that the current
     406             :              * blockno of the main iterator and that of the prefetch iterator
     407             :              * are same.  It's possible that whatever blockno we are
     408             :              * prefetching will be processed by another process.  Therefore,
     409             :              * we don't validate the blockno here as we do in non-parallel
     410             :              * case.
     411             :              */
     412          44 :             if (prefetch_iterator)
     413          44 :                 tbm_shared_iterate(prefetch_iterator);
     414             :         }
     415             :     }
     416             : #endif                          /* USE_PREFETCH */
     417             : }
     418             : 
     419             : /*
     420             :  * BitmapAdjustPrefetchTarget - Adjust the prefetch target
     421             :  *
     422             :  * Increase prefetch target if it's not yet at the max.  Note that
     423             :  * we will increase it to zero after fetching the very first
     424             :  * page/tuple, then to one after the second tuple is fetched, then
     425             :  * it doubles as later pages are fetched.
     426             :  */
     427             : static inline void
     428      132444 : BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
     429             : {
     430             : #ifdef USE_PREFETCH
     431      132444 :     ParallelBitmapHeapState *pstate = node->pstate;
     432             : 
     433      132444 :     if (pstate == NULL)
     434             :     {
     435      113704 :         if (node->prefetch_target >= node->prefetch_maximum)
     436             :              /* don't increase any further */ ;
     437        8090 :         else if (node->prefetch_target >= node->prefetch_maximum / 2)
     438          52 :             node->prefetch_target = node->prefetch_maximum;
     439        8038 :         else if (node->prefetch_target > 0)
     440           0 :             node->prefetch_target *= 2;
     441             :         else
     442        8038 :             node->prefetch_target++;
     443      113704 :         return;
     444             :     }
     445             : 
     446             :     /* Do an unlocked check first to save spinlock acquisitions. */
     447       18740 :     if (pstate->prefetch_target < node->prefetch_maximum)
     448             :     {
     449         168 :         SpinLockAcquire(&pstate->mutex);
     450         168 :         if (pstate->prefetch_target >= node->prefetch_maximum)
     451             :              /* don't increase any further */ ;
     452         168 :         else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
     453          40 :             pstate->prefetch_target = node->prefetch_maximum;
     454         128 :         else if (pstate->prefetch_target > 0)
     455          84 :             pstate->prefetch_target *= 2;
     456             :         else
     457          44 :             pstate->prefetch_target++;
     458         168 :         SpinLockRelease(&pstate->mutex);
     459             :     }
     460             : #endif                          /* USE_PREFETCH */
     461             : }
     462             : 
     463             : /*
     464             :  * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
     465             :  */
     466             : static inline void
     467     2375092 : BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
     468             : {
     469             : #ifdef USE_PREFETCH
     470     2375092 :     ParallelBitmapHeapState *pstate = node->pstate;
     471             : 
     472     2375092 :     if (pstate == NULL)
     473             :     {
     474     1578152 :         TBMIterator *prefetch_iterator = node->prefetch_iterator;
     475             : 
     476     1578152 :         if (prefetch_iterator)
     477             :         {
     478     3168240 :             while (node->prefetch_pages < node->prefetch_target)
     479             :             {
     480      114924 :                 TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
     481             :                 bool        skip_fetch;
     482             : 
     483      114924 :                 if (tbmpre == NULL)
     484             :                 {
     485             :                     /* No more pages to prefetch */
     486        7948 :                     tbm_end_iterate(prefetch_iterator);
     487        7948 :                     node->prefetch_iterator = NULL;
     488        7948 :                     break;
     489             :                 }
     490      106976 :                 node->prefetch_pages++;
     491             : 
     492             :                 /*
     493             :                  * If we expect not to have to actually read this heap page,
     494             :                  * skip this prefetch call, but continue to run the prefetch
     495             :                  * logic normally.  (Would it be better not to increment
     496             :                  * prefetch_pages?)
     497             :                  *
     498             :                  * This depends on the assumption that the index AM will
     499             :                  * report the same recheck flag for this future heap page as
     500             :                  * it did for the current heap page; which is not a certainty
     501             :                  * but is true in many cases.
     502             :                  */
     503      262984 :                 skip_fetch = (node->can_skip_fetch &&
     504      148402 :                               (node->tbmres ? !node->tbmres->recheck : false) &&
     505       16910 :                               VM_ALL_VISIBLE(node->ss.ss_currentRelation,
     506             :                                              tbmpre->blockno,
     507             :                                              &node->pvmbuffer));
     508             : 
     509      106976 :                 if (!skip_fetch)
     510      106312 :                     PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
     511             :             }
     512             :         }
     513             : 
     514     1578152 :         return;
     515             :     }
     516             : 
     517      796940 :     if (pstate->prefetch_pages < pstate->prefetch_target)
     518             :     {
     519      340308 :         TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
     520             : 
     521      340308 :         if (prefetch_iterator)
     522             :         {
     523             :             while (1)
     524       18696 :             {
     525             :                 TBMIterateResult *tbmpre;
     526       31392 :                 bool        do_prefetch = false;
     527             :                 bool        skip_fetch;
     528             : 
     529             :                 /*
     530             :                  * Recheck under the mutex. If some other process has already
     531             :                  * done enough prefetching then we need not to do anything.
     532             :                  */
     533       31392 :                 SpinLockAcquire(&pstate->mutex);
     534       31392 :                 if (pstate->prefetch_pages < pstate->prefetch_target)
     535             :                 {
     536       18740 :                     pstate->prefetch_pages++;
     537       18740 :                     do_prefetch = true;
     538             :                 }
     539       31392 :                 SpinLockRelease(&pstate->mutex);
     540             : 
     541       31392 :                 if (!do_prefetch)
     542       12652 :                     return;
     543             : 
     544       18740 :                 tbmpre = tbm_shared_iterate(prefetch_iterator);
     545       18740 :                 if (tbmpre == NULL)
     546             :                 {
     547             :                     /* No more pages to prefetch */
     548          44 :                     tbm_end_shared_iterate(prefetch_iterator);
     549          44 :                     node->shared_prefetch_iterator = NULL;
     550          44 :                     break;
     551             :                 }
     552             : 
     553             :                 /* As above, skip prefetch if we expect not to need page */
     554       74784 :                 skip_fetch = (node->can_skip_fetch &&
     555       53724 :                               (node->tbmres ? !node->tbmres->recheck : false) &&
     556       16332 :                               VM_ALL_VISIBLE(node->ss.ss_currentRelation,
     557             :                                              tbmpre->blockno,
     558             :                                              &node->pvmbuffer));
     559             : 
     560       18696 :                 if (!skip_fetch)
     561        4936 :                     PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
     562             :             }
     563             :         }
     564             :     }
     565             : #endif                          /* USE_PREFETCH */
     566             : }
     567             : 
     568             : /*
     569             :  * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
     570             :  */
     571             : static bool
     572           0 : BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
     573             : {
     574             :     ExprContext *econtext;
     575             : 
     576             :     /*
     577             :      * extract necessary information from index scan node
     578             :      */
     579           0 :     econtext = node->ss.ps.ps_ExprContext;
     580             : 
     581             :     /* Does the tuple meet the original qual conditions? */
     582           0 :     econtext->ecxt_scantuple = slot;
     583           0 :     return ExecQualAndReset(node->bitmapqualorig, econtext);
     584             : }
     585             : 
     586             : /* ----------------------------------------------------------------
     587             :  *      ExecBitmapHeapScan(node)
     588             :  * ----------------------------------------------------------------
     589             :  */
     590             : static TupleTableSlot *
     591     1947766 : ExecBitmapHeapScan(PlanState *pstate)
     592             : {
     593     1947766 :     BitmapHeapScanState *node = castNode(BitmapHeapScanState, pstate);
     594             : 
     595     1947766 :     return ExecScan(&node->ss,
     596             :                     (ExecScanAccessMtd) BitmapHeapNext,
     597             :                     (ExecScanRecheckMtd) BitmapHeapRecheck);
     598             : }
     599             : 
     600             : /* ----------------------------------------------------------------
     601             :  *      ExecReScanBitmapHeapScan(node)
     602             :  * ----------------------------------------------------------------
     603             :  */
     604             : void
     605        2434 : ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
     606             : {
     607        2434 :     PlanState  *outerPlan = outerPlanState(node);
     608             : 
     609             :     /* rescan to release any page pin */
     610        2434 :     table_rescan(node->ss.ss_currentScanDesc, NULL);
     611             : 
     612             :     /* release bitmaps and buffers if any */
     613        2434 :     if (node->tbmiterator)
     614        1580 :         tbm_end_iterate(node->tbmiterator);
     615        2434 :     if (node->prefetch_iterator)
     616         798 :         tbm_end_iterate(node->prefetch_iterator);
     617        2434 :     if (node->shared_tbmiterator)
     618          36 :         tbm_end_shared_iterate(node->shared_tbmiterator);
     619        2434 :     if (node->shared_prefetch_iterator)
     620           0 :         tbm_end_shared_iterate(node->shared_prefetch_iterator);
     621        2434 :     if (node->tbm)
     622        1616 :         tbm_free(node->tbm);
     623        2434 :     if (node->vmbuffer != InvalidBuffer)
     624          36 :         ReleaseBuffer(node->vmbuffer);
     625        2434 :     if (node->pvmbuffer != InvalidBuffer)
     626          36 :         ReleaseBuffer(node->pvmbuffer);
     627        2434 :     node->tbm = NULL;
     628        2434 :     node->tbmiterator = NULL;
     629        2434 :     node->tbmres = NULL;
     630        2434 :     node->prefetch_iterator = NULL;
     631        2434 :     node->initialized = false;
     632        2434 :     node->shared_tbmiterator = NULL;
     633        2434 :     node->shared_prefetch_iterator = NULL;
     634        2434 :     node->vmbuffer = InvalidBuffer;
     635        2434 :     node->pvmbuffer = InvalidBuffer;
     636             : 
     637        2434 :     ExecScanReScan(&node->ss);
     638             : 
     639             :     /*
     640             :      * if chgParam of subnode is not null then plan will be re-scanned by
     641             :      * first ExecProcNode.
     642             :      */
     643        2434 :     if (outerPlan->chgParam == NULL)
     644         340 :         ExecReScan(outerPlan);
     645        2434 : }
     646             : 
     647             : /* ----------------------------------------------------------------
     648             :  *      ExecEndBitmapHeapScan
     649             :  * ----------------------------------------------------------------
     650             :  */
     651             : void
     652       19778 : ExecEndBitmapHeapScan(BitmapHeapScanState *node)
     653             : {
     654             :     TableScanDesc scanDesc;
     655             : 
     656             :     /*
     657             :      * extract information from the node
     658             :      */
     659       19778 :     scanDesc = node->ss.ss_currentScanDesc;
     660             : 
     661             :     /*
     662             :      * Free the exprcontext
     663             :      */
     664       19778 :     ExecFreeExprContext(&node->ss.ps);
     665             : 
     666             :     /*
     667             :      * clear out tuple table slots
     668             :      */
     669       19778 :     if (node->ss.ps.ps_ResultTupleSlot)
     670       17086 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     671       19778 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
     672             : 
     673             :     /*
     674             :      * close down subplans
     675             :      */
     676       19778 :     ExecEndNode(outerPlanState(node));
     677             : 
     678             :     /*
     679             :      * release bitmaps and buffers if any
     680             :      */
     681       19778 :     if (node->tbmiterator)
     682       12088 :         tbm_end_iterate(node->tbmiterator);
     683       19778 :     if (node->prefetch_iterator)
     684        4954 :         tbm_end_iterate(node->prefetch_iterator);
     685       19778 :     if (node->tbm)
     686       12096 :         tbm_free(node->tbm);
     687       19778 :     if (node->shared_tbmiterator)
     688         184 :         tbm_end_shared_iterate(node->shared_tbmiterator);
     689       19778 :     if (node->shared_prefetch_iterator)
     690         176 :         tbm_end_shared_iterate(node->shared_prefetch_iterator);
     691       19778 :     if (node->vmbuffer != InvalidBuffer)
     692          52 :         ReleaseBuffer(node->vmbuffer);
     693       19778 :     if (node->pvmbuffer != InvalidBuffer)
     694          40 :         ReleaseBuffer(node->pvmbuffer);
     695             : 
     696             :     /*
     697             :      * close heap scan
     698             :      */
     699       19778 :     table_endscan(scanDesc);
     700       19778 : }
     701             : 
     702             : /* ----------------------------------------------------------------
     703             :  *      ExecInitBitmapHeapScan
     704             :  *
     705             :  *      Initializes the scan's state information.
     706             :  * ----------------------------------------------------------------
     707             :  */
     708             : BitmapHeapScanState *
     709       19820 : ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
     710             : {
     711             :     BitmapHeapScanState *scanstate;
     712             :     Relation    currentRelation;
     713             :     int         io_concurrency;
     714             : 
     715             :     /* check for unsupported flags */
     716             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     717             : 
     718             :     /*
     719             :      * Assert caller didn't ask for an unsafe snapshot --- see comments at
     720             :      * head of file.
     721             :      */
     722             :     Assert(IsMVCCSnapshot(estate->es_snapshot));
     723             : 
     724             :     /*
     725             :      * create state structure
     726             :      */
     727       19820 :     scanstate = makeNode(BitmapHeapScanState);
     728       19820 :     scanstate->ss.ps.plan = (Plan *) node;
     729       19820 :     scanstate->ss.ps.state = estate;
     730       19820 :     scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
     731             : 
     732       19820 :     scanstate->tbm = NULL;
     733       19820 :     scanstate->tbmiterator = NULL;
     734       19820 :     scanstate->tbmres = NULL;
     735       19820 :     scanstate->return_empty_tuples = 0;
     736       19820 :     scanstate->vmbuffer = InvalidBuffer;
     737       19820 :     scanstate->pvmbuffer = InvalidBuffer;
     738       19820 :     scanstate->exact_pages = 0;
     739       19820 :     scanstate->lossy_pages = 0;
     740       19820 :     scanstate->prefetch_iterator = NULL;
     741       19820 :     scanstate->prefetch_pages = 0;
     742       19820 :     scanstate->prefetch_target = 0;
     743             :     /* may be updated below */
     744       19820 :     scanstate->prefetch_maximum = target_prefetch_pages;
     745       19820 :     scanstate->pscan_len = 0;
     746       19820 :     scanstate->initialized = false;
     747       19820 :     scanstate->shared_tbmiterator = NULL;
     748       19820 :     scanstate->shared_prefetch_iterator = NULL;
     749       19820 :     scanstate->pstate = NULL;
     750             : 
     751             :     /*
     752             :      * We can potentially skip fetching heap pages if we do not need any
     753             :      * columns of the table, either for checking non-indexable quals or for
     754             :      * returning data.  This test is a bit simplistic, as it checks the
     755             :      * stronger condition that there's no qual or return tlist at all.  But in
     756             :      * most cases it's probably not worth working harder than that.
     757             :      */
     758       38492 :     scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
     759       18672 :                                  node->scan.plan.targetlist == NIL);
     760             : 
     761             :     /*
     762             :      * Miscellaneous initialization
     763             :      *
     764             :      * create expression context for node
     765             :      */
     766       19820 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     767             : 
     768             :     /*
     769             :      * open the scan relation
     770             :      */
     771       19820 :     currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
     772             : 
     773             :     /*
     774             :      * initialize child nodes
     775             :      */
     776       19820 :     outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
     777             : 
     778             :     /*
     779             :      * get the scan type from the relation descriptor.
     780             :      */
     781       19820 :     ExecInitScanTupleSlot(estate, &scanstate->ss,
     782             :                           RelationGetDescr(currentRelation),
     783             :                           table_slot_callbacks(currentRelation));
     784             : 
     785             :     /*
     786             :      * Initialize result type and projection.
     787             :      */
     788       19820 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     789       19820 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     790             : 
     791             :     /*
     792             :      * initialize child expressions
     793             :      */
     794       19820 :     scanstate->ss.ps.qual =
     795       19820 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     796       19820 :     scanstate->bitmapqualorig =
     797       19820 :         ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
     798             : 
     799             :     /*
     800             :      * Determine the maximum for prefetch_target.  If the tablespace has a
     801             :      * specific IO concurrency set, use that to compute the corresponding
     802             :      * maximum value; otherwise, we already initialized to the value computed
     803             :      * by the GUC machinery.
     804             :      */
     805       19820 :     io_concurrency =
     806       19820 :         get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
     807       19820 :     if (io_concurrency != effective_io_concurrency)
     808             :     {
     809             :         double      maximum;
     810             : 
     811           0 :         if (ComputeIoConcurrency(io_concurrency, &maximum))
     812           0 :             scanstate->prefetch_maximum = rint(maximum);
     813             :     }
     814             : 
     815       19820 :     scanstate->ss.ss_currentRelation = currentRelation;
     816             : 
     817       19820 :     scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
     818             :                                                           estate->es_snapshot,
     819             :                                                           0,
     820             :                                                           NULL);
     821             : 
     822             :     /*
     823             :      * all done.
     824             :      */
     825       19820 :     return scanstate;
     826             : }
     827             : 
     828             : /*----------------
     829             :  *      BitmapShouldInitializeSharedState
     830             :  *
     831             :  *      The first process to come here and see the state to the BM_INITIAL
     832             :  *      will become the leader for the parallel bitmap scan and will be
     833             :  *      responsible for populating the TIDBitmap.  The other processes will
     834             :  *      be blocked by the condition variable until the leader wakes them up.
     835             :  * ---------------
     836             :  */
     837             : static bool
     838         220 : BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
     839             : {
     840             :     SharedBitmapState state;
     841             : 
     842             :     while (1)
     843             :     {
     844         220 :         SpinLockAcquire(&pstate->mutex);
     845         220 :         state = pstate->state;
     846         220 :         if (pstate->state == BM_INITIAL)
     847          44 :             pstate->state = BM_INPROGRESS;
     848         220 :         SpinLockRelease(&pstate->mutex);
     849             : 
     850             :         /* Exit if bitmap is done, or if we're the leader. */
     851         220 :         if (state != BM_INPROGRESS)
     852         220 :             break;
     853             : 
     854             :         /* Wait for the leader to wake us up. */
     855           0 :         ConditionVariableSleep(&pstate->cv, WAIT_EVENT_PARALLEL_BITMAP_SCAN);
     856             :     }
     857             : 
     858         220 :     ConditionVariableCancelSleep();
     859             : 
     860         220 :     return (state == BM_INITIAL);
     861             : }
     862             : 
     863             : /* ----------------------------------------------------------------
     864             :  *      ExecBitmapHeapEstimate
     865             :  *
     866             :  *      Compute the amount of space we'll need in the parallel
     867             :  *      query DSM, and inform pcxt->estimator about our needs.
     868             :  * ----------------------------------------------------------------
     869             :  */
     870             : void
     871           8 : ExecBitmapHeapEstimate(BitmapHeapScanState *node,
     872             :                        ParallelContext *pcxt)
     873             : {
     874           8 :     EState     *estate = node->ss.ps.state;
     875             : 
     876           8 :     node->pscan_len = add_size(offsetof(ParallelBitmapHeapState,
     877             :                                         phs_snapshot_data),
     878             :                                EstimateSnapshotSpace(estate->es_snapshot));
     879             : 
     880           8 :     shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
     881           8 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
     882           8 : }
     883             : 
     884             : /* ----------------------------------------------------------------
     885             :  *      ExecBitmapHeapInitializeDSM
     886             :  *
     887             :  *      Set up a parallel bitmap heap scan descriptor.
     888             :  * ----------------------------------------------------------------
     889             :  */
     890             : void
     891           8 : ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
     892             :                             ParallelContext *pcxt)
     893             : {
     894             :     ParallelBitmapHeapState *pstate;
     895           8 :     EState     *estate = node->ss.ps.state;
     896           8 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
     897             : 
     898             :     /* If there's no DSA, there are no workers; initialize nothing. */
     899           8 :     if (dsa == NULL)
     900           0 :         return;
     901             : 
     902           8 :     pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
     903             : 
     904           8 :     pstate->tbmiterator = 0;
     905           8 :     pstate->prefetch_iterator = 0;
     906             : 
     907             :     /* Initialize the mutex */
     908           8 :     SpinLockInit(&pstate->mutex);
     909           8 :     pstate->prefetch_pages = 0;
     910           8 :     pstate->prefetch_target = 0;
     911           8 :     pstate->state = BM_INITIAL;
     912             : 
     913           8 :     ConditionVariableInit(&pstate->cv);
     914           8 :     SerializeSnapshot(estate->es_snapshot, pstate->phs_snapshot_data);
     915             : 
     916           8 :     shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
     917           8 :     node->pstate = pstate;
     918             : }
     919             : 
     920             : /* ----------------------------------------------------------------
     921             :  *      ExecBitmapHeapReInitializeDSM
     922             :  *
     923             :  *      Reset shared state before beginning a fresh scan.
     924             :  * ----------------------------------------------------------------
     925             :  */
     926             : void
     927          36 : ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
     928             :                               ParallelContext *pcxt)
     929             : {
     930          36 :     ParallelBitmapHeapState *pstate = node->pstate;
     931          36 :     dsa_area   *dsa = node->ss.ps.state->es_query_dsa;
     932             : 
     933             :     /* If there's no DSA, there are no workers; do nothing. */
     934          36 :     if (dsa == NULL)
     935           0 :         return;
     936             : 
     937          36 :     pstate->state = BM_INITIAL;
     938             : 
     939          36 :     if (DsaPointerIsValid(pstate->tbmiterator))
     940          36 :         tbm_free_shared_area(dsa, pstate->tbmiterator);
     941             : 
     942          36 :     if (DsaPointerIsValid(pstate->prefetch_iterator))
     943          36 :         tbm_free_shared_area(dsa, pstate->prefetch_iterator);
     944             : 
     945          36 :     pstate->tbmiterator = InvalidDsaPointer;
     946          36 :     pstate->prefetch_iterator = InvalidDsaPointer;
     947             : }
     948             : 
     949             : /* ----------------------------------------------------------------
     950             :  *      ExecBitmapHeapInitializeWorker
     951             :  *
     952             :  *      Copy relevant information from TOC into planstate.
     953             :  * ----------------------------------------------------------------
     954             :  */
     955             : void
     956         176 : ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
     957             :                                ParallelWorkerContext *pwcxt)
     958             : {
     959             :     ParallelBitmapHeapState *pstate;
     960             :     Snapshot    snapshot;
     961             : 
     962             :     Assert(node->ss.ps.state->es_query_dsa != NULL);
     963             : 
     964         176 :     pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
     965         176 :     node->pstate = pstate;
     966             : 
     967         176 :     snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
     968         176 :     table_scan_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
     969         176 : }

Generated by: LCOV version 1.13