PostgreSQL Source Code  git master
nodeBitmapHeapscan.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/relscan.h"
#include "access/tableam.h"
#include "access/transam.h"
#include "access/visibilitymap.h"
#include "executor/execdebug.h"
#include "executor/nodeBitmapHeapscan.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/spccache.h"
Include dependency graph for nodeBitmapHeapscan.c:

Go to the source code of this file.

Functions

static TupleTableSlotBitmapHeapNext (BitmapHeapScanState *node)
 
static void BitmapDoneInitializingSharedState (ParallelBitmapHeapState *pstate)
 
static void BitmapAdjustPrefetchIterator (BitmapHeapScanState *node, TBMIterateResult *tbmres)
 
static void BitmapAdjustPrefetchTarget (BitmapHeapScanState *node)
 
static void BitmapPrefetch (BitmapHeapScanState *node, TableScanDesc scan)
 
static bool BitmapShouldInitializeSharedState (ParallelBitmapHeapState *pstate)
 
static bool BitmapHeapRecheck (BitmapHeapScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecBitmapHeapScan (PlanState *pstate)
 
void ExecReScanBitmapHeapScan (BitmapHeapScanState *node)
 
void ExecEndBitmapHeapScan (BitmapHeapScanState *node)
 
BitmapHeapScanStateExecInitBitmapHeapScan (BitmapHeapScan *node, EState *estate, int eflags)
 
void ExecBitmapHeapEstimate (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapInitializeDSM (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapReInitializeDSM (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapInitializeWorker (BitmapHeapScanState *node, ParallelWorkerContext *pwcxt)
 

Function Documentation

◆ BitmapAdjustPrefetchIterator()

static void BitmapAdjustPrefetchIterator ( BitmapHeapScanState node,
TBMIterateResult tbmres 
)
inlinestatic

Definition at line 360 of file nodeBitmapHeapscan.c.

362 {
363 #ifdef USE_PREFETCH
364  ParallelBitmapHeapState *pstate = node->pstate;
365 
366  if (pstate == NULL)
367  {
368  TBMIterator *prefetch_iterator = node->prefetch_iterator;
369 
370  if (node->prefetch_pages > 0)
371  {
372  /* The main iterator has closed the distance by one page */
373  node->prefetch_pages--;
374  }
375  else if (prefetch_iterator)
376  {
377  /* Do not let the prefetch iterator get behind the main one */
378  TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
379 
380  if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
381  elog(ERROR, "prefetch and main iterators are out of sync");
382  }
383  return;
384  }
385 
386  if (node->prefetch_maximum > 0)
387  {
388  TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
389 
390  SpinLockAcquire(&pstate->mutex);
391  if (pstate->prefetch_pages > 0)
392  {
393  pstate->prefetch_pages--;
394  SpinLockRelease(&pstate->mutex);
395  }
396  else
397  {
398  /* Release the mutex before iterating */
399  SpinLockRelease(&pstate->mutex);
400 
401  /*
402  * In case of shared mode, we can not ensure that the current
403  * blockno of the main iterator and that of the prefetch iterator
404  * are same. It's possible that whatever blockno we are
405  * prefetching will be processed by another process. Therefore,
406  * we don't validate the blockno here as we do in non-parallel
407  * case.
408  */
409  if (prefetch_iterator)
410  tbm_shared_iterate(prefetch_iterator);
411  }
412  }
413 #endif /* USE_PREFETCH */
414 }
#define ERROR
Definition: elog.h:39
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1733
TBMIterator * prefetch_iterator
Definition: execnodes.h:1725
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1732
BlockNumber blockno
Definition: tidbitmap.h:42
TBMIterateResult * tbm_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1051
TBMIterateResult * tbm_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:970

References TBMIterateResult::blockno, elog(), ERROR, ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, BitmapHeapScanState::pstate, BitmapHeapScanState::shared_prefetch_iterator, SpinLockAcquire, SpinLockRelease, tbm_iterate(), and tbm_shared_iterate().

Referenced by BitmapHeapNext().

◆ BitmapAdjustPrefetchTarget()

static void BitmapAdjustPrefetchTarget ( BitmapHeapScanState node)
inlinestatic

Definition at line 425 of file nodeBitmapHeapscan.c.

426 {
427 #ifdef USE_PREFETCH
428  ParallelBitmapHeapState *pstate = node->pstate;
429 
430  if (pstate == NULL)
431  {
432  if (node->prefetch_target >= node->prefetch_maximum)
433  /* don't increase any further */ ;
434  else if (node->prefetch_target >= node->prefetch_maximum / 2)
435  node->prefetch_target = node->prefetch_maximum;
436  else if (node->prefetch_target > 0)
437  node->prefetch_target *= 2;
438  else
439  node->prefetch_target++;
440  return;
441  }
442 
443  /* Do an unlocked check first to save spinlock acquisitions. */
444  if (pstate->prefetch_target < node->prefetch_maximum)
445  {
446  SpinLockAcquire(&pstate->mutex);
447  if (pstate->prefetch_target >= node->prefetch_maximum)
448  /* don't increase any further */ ;
449  else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
450  pstate->prefetch_target = node->prefetch_maximum;
451  else if (pstate->prefetch_target > 0)
452  pstate->prefetch_target *= 2;
453  else
454  pstate->prefetch_target++;
455  SpinLockRelease(&pstate->mutex);
456  }
457 #endif /* USE_PREFETCH */
458 }

References ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, BitmapHeapScanState::pstate, SpinLockAcquire, and SpinLockRelease.

Referenced by BitmapHeapNext().

◆ BitmapDoneInitializingSharedState()

static void BitmapDoneInitializingSharedState ( ParallelBitmapHeapState pstate)
inlinestatic

Definition at line 348 of file nodeBitmapHeapscan.c.

349 {
350  SpinLockAcquire(&pstate->mutex);
351  pstate->state = BM_FINISHED;
352  SpinLockRelease(&pstate->mutex);
353  ConditionVariableBroadcast(&pstate->cv);
354 }
void ConditionVariableBroadcast(ConditionVariable *cv)
@ BM_FINISHED
Definition: execnodes.h:1660
SharedBitmapState state
Definition: execnodes.h:1683
ConditionVariable cv
Definition: execnodes.h:1684

References BM_FINISHED, ConditionVariableBroadcast(), ParallelBitmapHeapState::cv, ParallelBitmapHeapState::mutex, SpinLockAcquire, SpinLockRelease, and ParallelBitmapHeapState::state.

Referenced by BitmapHeapNext().

◆ BitmapHeapNext()

static TupleTableSlot * BitmapHeapNext ( BitmapHeapScanState node)
static

Definition at line 72 of file nodeBitmapHeapscan.c.

73 {
74  ExprContext *econtext;
75  TableScanDesc scan;
76  TIDBitmap *tbm;
77  TBMIterator *tbmiterator = NULL;
78  TBMSharedIterator *shared_tbmiterator = NULL;
79  TBMIterateResult *tbmres;
80  TupleTableSlot *slot;
81  ParallelBitmapHeapState *pstate = node->pstate;
82  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
83 
84  /*
85  * extract necessary information from index scan node
86  */
87  econtext = node->ss.ps.ps_ExprContext;
88  slot = node->ss.ss_ScanTupleSlot;
89  scan = node->ss.ss_currentScanDesc;
90  tbm = node->tbm;
91  if (pstate == NULL)
92  tbmiterator = node->tbmiterator;
93  else
94  shared_tbmiterator = node->shared_tbmiterator;
95  tbmres = node->tbmres;
96 
97  /*
98  * If we haven't yet performed the underlying index scan, do it, and begin
99  * the iteration over the bitmap.
100  *
101  * For prefetching, we use *two* iterators, one for the pages we are
102  * actually scanning and another that runs ahead of the first for
103  * prefetching. node->prefetch_pages tracks exactly how many pages ahead
104  * the prefetch iterator is. Also, node->prefetch_target tracks the
105  * desired prefetch distance, which starts small and increases up to the
106  * node->prefetch_maximum. This is to avoid doing a lot of prefetching in
107  * a scan that stops after a few tuples because of a LIMIT.
108  */
109  if (!node->initialized)
110  {
111  if (!pstate)
112  {
113  tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
114 
115  if (!tbm || !IsA(tbm, TIDBitmap))
116  elog(ERROR, "unrecognized result from subplan");
117 
118  node->tbm = tbm;
119  node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
120  node->tbmres = tbmres = NULL;
121 
122 #ifdef USE_PREFETCH
123  if (node->prefetch_maximum > 0)
124  {
126  node->prefetch_pages = 0;
127  node->prefetch_target = -1;
128  }
129 #endif /* USE_PREFETCH */
130  }
131  else
132  {
133  /*
134  * The leader will immediately come out of the function, but
135  * others will be blocked until leader populates the TBM and wakes
136  * them up.
137  */
139  {
140  tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
141  if (!tbm || !IsA(tbm, TIDBitmap))
142  elog(ERROR, "unrecognized result from subplan");
143 
144  node->tbm = tbm;
145 
146  /*
147  * Prepare to iterate over the TBM. This will return the
148  * dsa_pointer of the iterator state which will be used by
149  * multiple processes to iterate jointly.
150  */
152 #ifdef USE_PREFETCH
153  if (node->prefetch_maximum > 0)
154  {
155  pstate->prefetch_iterator =
157 
158  /*
159  * We don't need the mutex here as we haven't yet woke up
160  * others.
161  */
162  pstate->prefetch_pages = 0;
163  pstate->prefetch_target = -1;
164  }
165 #endif
166 
167  /* We have initialized the shared state so wake up others. */
169  }
170 
171  /* Allocate a private iterator and attach the shared state to it */
172  node->shared_tbmiterator = shared_tbmiterator =
174  node->tbmres = tbmres = NULL;
175 
176 #ifdef USE_PREFETCH
177  if (node->prefetch_maximum > 0)
178  {
181  }
182 #endif /* USE_PREFETCH */
183  }
184  node->initialized = true;
185  }
186 
187  for (;;)
188  {
189  bool skip_fetch;
190 
192 
193  /*
194  * Get next page of results if needed
195  */
196  if (tbmres == NULL)
197  {
198  if (!pstate)
199  node->tbmres = tbmres = tbm_iterate(tbmiterator);
200  else
201  node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
202  if (tbmres == NULL)
203  {
204  /* no more entries in the bitmap */
205  break;
206  }
207 
208  BitmapAdjustPrefetchIterator(node, tbmres);
209 
210  /*
211  * We can skip fetching the heap page if we don't need any fields
212  * from the heap, and the bitmap entries don't need rechecking,
213  * and all tuples on the page are visible to our transaction.
214  *
215  * XXX: It's a layering violation that we do these checks above
216  * tableam, they should probably moved below it at some point.
217  */
218  skip_fetch = (node->can_skip_fetch &&
219  !tbmres->recheck &&
221  tbmres->blockno,
222  &node->vmbuffer));
223 
224  if (skip_fetch)
225  {
226  /* can't be lossy in the skip_fetch case */
227  Assert(tbmres->ntuples >= 0);
228 
229  /*
230  * The number of tuples on this page is put into
231  * node->return_empty_tuples.
232  */
233  node->return_empty_tuples = tbmres->ntuples;
234  }
235  else if (!table_scan_bitmap_next_block(scan, tbmres))
236  {
237  /* AM doesn't think this block is valid, skip */
238  continue;
239  }
240 
241  if (tbmres->ntuples >= 0)
242  node->exact_pages++;
243  else
244  node->lossy_pages++;
245 
246  /* Adjust the prefetch target */
248  }
249  else
250  {
251  /*
252  * Continuing in previously obtained page.
253  */
254 
255 #ifdef USE_PREFETCH
256 
257  /*
258  * Try to prefetch at least a few pages even before we get to the
259  * second page if we don't stop reading after the first tuple.
260  */
261  if (!pstate)
262  {
263  if (node->prefetch_target < node->prefetch_maximum)
264  node->prefetch_target++;
265  }
266  else if (pstate->prefetch_target < node->prefetch_maximum)
267  {
268  /* take spinlock while updating shared state */
269  SpinLockAcquire(&pstate->mutex);
270  if (pstate->prefetch_target < node->prefetch_maximum)
271  pstate->prefetch_target++;
272  SpinLockRelease(&pstate->mutex);
273  }
274 #endif /* USE_PREFETCH */
275  }
276 
277  /*
278  * We issue prefetch requests *after* fetching the current page to try
279  * to avoid having prefetching interfere with the main I/O. Also, this
280  * should happen only when we have determined there is still something
281  * to do on the current page, else we may uselessly prefetch the same
282  * page we are just about to request for real.
283  *
284  * XXX: It's a layering violation that we do these checks above
285  * tableam, they should probably moved below it at some point.
286  */
287  BitmapPrefetch(node, scan);
288 
289  if (node->return_empty_tuples > 0)
290  {
291  /*
292  * If we don't have to fetch the tuple, just return nulls.
293  */
294  ExecStoreAllNullTuple(slot);
295 
296  if (--node->return_empty_tuples == 0)
297  {
298  /* no more tuples to return in the next round */
299  node->tbmres = tbmres = NULL;
300  }
301  }
302  else
303  {
304  /*
305  * Attempt to fetch tuple from AM.
306  */
307  if (!table_scan_bitmap_next_tuple(scan, tbmres, slot))
308  {
309  /* nothing more to look at on this page */
310  node->tbmres = tbmres = NULL;
311  continue;
312  }
313 
314  /*
315  * If we are using lossy info, we have to recheck the qual
316  * conditions at every tuple.
317  */
318  if (tbmres->recheck)
319  {
320  econtext->ecxt_scantuple = slot;
321  if (!ExecQualAndReset(node->bitmapqualorig, econtext))
322  {
323  /* Fails recheck, so drop it and loop back for another */
324  InstrCountFiltered2(node, 1);
325  ExecClearTuple(slot);
326  continue;
327  }
328  }
329  }
330 
331  /* OK to return this tuple */
332  return slot;
333  }
334 
335  /*
336  * if we get here it means we are at the end of the scan..
337  */
338  return ExecClearTuple(slot);
339 }
Node * MultiExecProcNode(PlanState *node)
Definition: execProcnode.c:502
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:1576
#define outerPlanState(node)
Definition: execnodes.h:1131
#define InstrCountFiltered2(node, delta)
Definition: execnodes.h:1144
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:438
Assert(fmt[strlen(fmt) - 1] !='\n')
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
static void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node, TBMIterateResult *tbmres)
static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
static void BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
static void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
static void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
ExprState * bitmapqualorig
Definition: execnodes.h:1715
TBMIterateResult * tbmres
Definition: execnodes.h:1718
TBMIterator * tbmiterator
Definition: execnodes.h:1717
TIDBitmap * tbm
Definition: execnodes.h:1716
TBMSharedIterator * shared_tbmiterator
Definition: execnodes.h:1731
struct dsa_area * es_query_dsa
Definition: execnodes.h:694
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:249
dsa_pointer tbmiterator
Definition: execnodes.h:1678
dsa_pointer prefetch_iterator
Definition: execnodes.h:1679
EState * state
Definition: execnodes.h:1037
ExprContext * ps_ExprContext
Definition: execnodes.h:1074
Relation ss_currentRelation
Definition: execnodes.h:1462
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1464
PlanState ps
Definition: execnodes.h:1461
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1463
Definition: dsa.c:367
static bool table_scan_bitmap_next_tuple(TableScanDesc scan, struct TBMIterateResult *tbmres, TupleTableSlot *slot)
Definition: tableam.h:1992
static bool table_scan_bitmap_next_block(TableScanDesc scan, struct TBMIterateResult *tbmres)
Definition: tableam.h:1968
TBMIterator * tbm_begin_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:688
TBMSharedIterator * tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:1464
dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:765
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:471
#define VM_ALL_VISIBLE(r, b, v)
Definition: visibilitymap.h:24

References Assert(), BitmapAdjustPrefetchIterator(), BitmapAdjustPrefetchTarget(), BitmapDoneInitializingSharedState(), BitmapPrefetch(), BitmapHeapScanState::bitmapqualorig, BitmapShouldInitializeSharedState(), TBMIterateResult::blockno, BitmapHeapScanState::can_skip_fetch, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_scantuple, elog(), ERROR, EState::es_query_dsa, BitmapHeapScanState::exact_pages, ExecClearTuple(), ExecQualAndReset(), ExecStoreAllNullTuple(), BitmapHeapScanState::initialized, InstrCountFiltered2, IsA, BitmapHeapScanState::lossy_pages, MultiExecProcNode(), ParallelBitmapHeapState::mutex, TBMIterateResult::ntuples, outerPlanState, ParallelBitmapHeapState::prefetch_iterator, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, ScanState::ps, PlanState::ps_ExprContext, BitmapHeapScanState::pstate, TBMIterateResult::recheck, BitmapHeapScanState::return_empty_tuples, BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, SpinLockAcquire, SpinLockRelease, BitmapHeapScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, PlanState::state, table_scan_bitmap_next_block(), table_scan_bitmap_next_tuple(), BitmapHeapScanState::tbm, tbm_attach_shared_iterate(), tbm_begin_iterate(), tbm_iterate(), tbm_prepare_shared_iterate(), tbm_shared_iterate(), ParallelBitmapHeapState::tbmiterator, BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, VM_ALL_VISIBLE, and BitmapHeapScanState::vmbuffer.

Referenced by ExecBitmapHeapScan().

◆ BitmapHeapRecheck()

static bool BitmapHeapRecheck ( BitmapHeapScanState node,
TupleTableSlot slot 
)
static

Definition at line 569 of file nodeBitmapHeapscan.c.

570 {
571  ExprContext *econtext;
572 
573  /*
574  * extract necessary information from index scan node
575  */
576  econtext = node->ss.ps.ps_ExprContext;
577 
578  /* Does the tuple meet the original qual conditions? */
579  econtext->ecxt_scantuple = slot;
580  return ExecQualAndReset(node->bitmapqualorig, econtext);
581 }

References BitmapHeapScanState::bitmapqualorig, ExprContext::ecxt_scantuple, ExecQualAndReset(), ScanState::ps, PlanState::ps_ExprContext, and BitmapHeapScanState::ss.

Referenced by ExecBitmapHeapScan().

◆ BitmapPrefetch()

static void BitmapPrefetch ( BitmapHeapScanState node,
TableScanDesc  scan 
)
inlinestatic

Definition at line 464 of file nodeBitmapHeapscan.c.

465 {
466 #ifdef USE_PREFETCH
467  ParallelBitmapHeapState *pstate = node->pstate;
468 
469  if (pstate == NULL)
470  {
471  TBMIterator *prefetch_iterator = node->prefetch_iterator;
472 
473  if (prefetch_iterator)
474  {
475  while (node->prefetch_pages < node->prefetch_target)
476  {
477  TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
478  bool skip_fetch;
479 
480  if (tbmpre == NULL)
481  {
482  /* No more pages to prefetch */
483  tbm_end_iterate(prefetch_iterator);
484  node->prefetch_iterator = NULL;
485  break;
486  }
487  node->prefetch_pages++;
488 
489  /*
490  * If we expect not to have to actually read this heap page,
491  * skip this prefetch call, but continue to run the prefetch
492  * logic normally. (Would it be better not to increment
493  * prefetch_pages?)
494  *
495  * This depends on the assumption that the index AM will
496  * report the same recheck flag for this future heap page as
497  * it did for the current heap page; which is not a certainty
498  * but is true in many cases.
499  */
500  skip_fetch = (node->can_skip_fetch &&
501  (node->tbmres ? !node->tbmres->recheck : false) &&
503  tbmpre->blockno,
504  &node->pvmbuffer));
505 
506  if (!skip_fetch)
507  PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
508  }
509  }
510 
511  return;
512  }
513 
514  if (pstate->prefetch_pages < pstate->prefetch_target)
515  {
516  TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
517 
518  if (prefetch_iterator)
519  {
520  while (1)
521  {
522  TBMIterateResult *tbmpre;
523  bool do_prefetch = false;
524  bool skip_fetch;
525 
526  /*
527  * Recheck under the mutex. If some other process has already
528  * done enough prefetching then we need not to do anything.
529  */
530  SpinLockAcquire(&pstate->mutex);
531  if (pstate->prefetch_pages < pstate->prefetch_target)
532  {
533  pstate->prefetch_pages++;
534  do_prefetch = true;
535  }
536  SpinLockRelease(&pstate->mutex);
537 
538  if (!do_prefetch)
539  return;
540 
541  tbmpre = tbm_shared_iterate(prefetch_iterator);
542  if (tbmpre == NULL)
543  {
544  /* No more pages to prefetch */
545  tbm_end_shared_iterate(prefetch_iterator);
546  node->shared_prefetch_iterator = NULL;
547  break;
548  }
549 
550  /* As above, skip prefetch if we expect not to need page */
551  skip_fetch = (node->can_skip_fetch &&
552  (node->tbmres ? !node->tbmres->recheck : false) &&
554  tbmpre->blockno,
555  &node->pvmbuffer));
556 
557  if (!skip_fetch)
558  PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
559  }
560  }
561  }
562 #endif /* USE_PREFETCH */
563 }
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:584
@ MAIN_FORKNUM
Definition: relpath.h:50
Relation rs_rd
Definition: relscan.h:34
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1145
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1157

References TBMIterateResult::blockno, BitmapHeapScanState::can_skip_fetch, MAIN_FORKNUM, ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_iterator, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, PrefetchBuffer(), BitmapHeapScanState::pstate, BitmapHeapScanState::pvmbuffer, TBMIterateResult::recheck, TableScanDescData::rs_rd, BitmapHeapScanState::shared_prefetch_iterator, SpinLockAcquire, SpinLockRelease, BitmapHeapScanState::ss, ScanState::ss_currentRelation, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_iterate(), tbm_shared_iterate(), BitmapHeapScanState::tbmres, and VM_ALL_VISIBLE.

Referenced by BitmapHeapNext().

◆ BitmapShouldInitializeSharedState()

static bool BitmapShouldInitializeSharedState ( ParallelBitmapHeapState pstate)
static

Definition at line 823 of file nodeBitmapHeapscan.c.

824 {
826 
827  while (1)
828  {
829  SpinLockAcquire(&pstate->mutex);
830  state = pstate->state;
831  if (pstate->state == BM_INITIAL)
832  pstate->state = BM_INPROGRESS;
833  SpinLockRelease(&pstate->mutex);
834 
835  /* Exit if bitmap is done, or if we're the leader. */
836  if (state != BM_INPROGRESS)
837  break;
838 
839  /* Wait for the leader to wake us up. */
841  }
842 
844 
845  return (state == BM_INITIAL);
846 }
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
void ConditionVariableCancelSleep(void)
SharedBitmapState
Definition: execnodes.h:1657
@ BM_INITIAL
Definition: execnodes.h:1658
@ BM_INPROGRESS
Definition: execnodes.h:1659
Definition: regguts.h:318
@ WAIT_EVENT_PARALLEL_BITMAP_SCAN
Definition: wait_event.h:117

References BM_INITIAL, BM_INPROGRESS, ConditionVariableCancelSleep(), ConditionVariableSleep(), ParallelBitmapHeapState::cv, ParallelBitmapHeapState::mutex, SpinLockAcquire, SpinLockRelease, ParallelBitmapHeapState::state, and WAIT_EVENT_PARALLEL_BITMAP_SCAN.

Referenced by BitmapHeapNext().

◆ ExecBitmapHeapEstimate()

void ExecBitmapHeapEstimate ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 856 of file nodeBitmapHeapscan.c.

858 {
859  EState *estate = node->ss.ps.state;
860 
861  node->pscan_len = add_size(offsetof(ParallelBitmapHeapState,
862  phs_snapshot_data),
864 
866  shm_toc_estimate_keys(&pcxt->estimator, 1);
867 }
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size EstimateSnapshotSpace(Snapshot snapshot)
Definition: snapmgr.c:2123
Snapshot es_snapshot
Definition: execnodes.h:616
shm_toc_estimator estimator
Definition: parallel.h:42

References add_size(), EState::es_snapshot, EstimateSnapshotSpace(), ParallelContext::estimator, ScanState::ps, BitmapHeapScanState::pscan_len, shm_toc_estimate_chunk, shm_toc_estimate_keys, BitmapHeapScanState::ss, and PlanState::state.

Referenced by ExecParallelEstimate().

◆ ExecBitmapHeapInitializeDSM()

void ExecBitmapHeapInitializeDSM ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 876 of file nodeBitmapHeapscan.c.

878 {
879  ParallelBitmapHeapState *pstate;
880  EState *estate = node->ss.ps.state;
881  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
882 
883  /* If there's no DSA, there are no workers; initialize nothing. */
884  if (dsa == NULL)
885  return;
886 
887  pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
888 
889  pstate->tbmiterator = 0;
890  pstate->prefetch_iterator = 0;
891 
892  /* Initialize the mutex */
893  SpinLockInit(&pstate->mutex);
894  pstate->prefetch_pages = 0;
895  pstate->prefetch_target = 0;
896  pstate->state = BM_INITIAL;
897 
898  ConditionVariableInit(&pstate->cv);
900 
901  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
902  node->pstate = pstate;
903 }
void ConditionVariableInit(ConditionVariable *cv)
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void SerializeSnapshot(Snapshot snapshot, char *start_address)
Definition: snapmgr.c:2147
#define SpinLockInit(lock)
Definition: spin.h:60
char phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:1685
shm_toc * toc
Definition: parallel.h:45
Plan * plan
Definition: execnodes.h:1035
int plan_node_id
Definition: plannodes.h:155

References BM_INITIAL, ConditionVariableInit(), ParallelBitmapHeapState::cv, EState::es_query_dsa, EState::es_snapshot, ParallelBitmapHeapState::mutex, ParallelBitmapHeapState::phs_snapshot_data, PlanState::plan, Plan::plan_node_id, ParallelBitmapHeapState::prefetch_iterator, ParallelBitmapHeapState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, ScanState::ps, BitmapHeapScanState::pscan_len, BitmapHeapScanState::pstate, SerializeSnapshot(), shm_toc_allocate(), shm_toc_insert(), SpinLockInit, BitmapHeapScanState::ss, PlanState::state, ParallelBitmapHeapState::state, ParallelBitmapHeapState::tbmiterator, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

◆ ExecBitmapHeapInitializeWorker()

void ExecBitmapHeapInitializeWorker ( BitmapHeapScanState node,
ParallelWorkerContext pwcxt 
)

Definition at line 941 of file nodeBitmapHeapscan.c.

943 {
944  ParallelBitmapHeapState *pstate;
945  Snapshot snapshot;
946 
947  Assert(node->ss.ps.state->es_query_dsa != NULL);
948 
949  pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
950  node->pstate = pstate;
951 
952  snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
954 }
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:2206
void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot)
Definition: tableam.c:124

References Assert(), EState::es_query_dsa, ParallelBitmapHeapState::phs_snapshot_data, PlanState::plan, Plan::plan_node_id, ScanState::ps, BitmapHeapScanState::pstate, RestoreSnapshot(), shm_toc_lookup(), BitmapHeapScanState::ss, ScanState::ss_currentScanDesc, PlanState::state, table_scan_update_snapshot(), and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

◆ ExecBitmapHeapReInitializeDSM()

void ExecBitmapHeapReInitializeDSM ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 912 of file nodeBitmapHeapscan.c.

914 {
915  ParallelBitmapHeapState *pstate = node->pstate;
916  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
917 
918  /* If there's no DSA, there are no workers; do nothing. */
919  if (dsa == NULL)
920  return;
921 
922  pstate->state = BM_INITIAL;
923 
924  if (DsaPointerIsValid(pstate->tbmiterator))
925  tbm_free_shared_area(dsa, pstate->tbmiterator);
926 
929 
930  pstate->tbmiterator = InvalidDsaPointer;
932 }
#define InvalidDsaPointer
Definition: dsa.h:78
#define DsaPointerIsValid(x)
Definition: dsa.h:81
void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:340

References BM_INITIAL, DsaPointerIsValid, EState::es_query_dsa, InvalidDsaPointer, ParallelBitmapHeapState::prefetch_iterator, ScanState::ps, BitmapHeapScanState::pstate, BitmapHeapScanState::ss, PlanState::state, ParallelBitmapHeapState::state, tbm_free_shared_area(), and ParallelBitmapHeapState::tbmiterator.

Referenced by ExecParallelReInitializeDSM().

◆ ExecBitmapHeapScan()

static TupleTableSlot* ExecBitmapHeapScan ( PlanState pstate)
static

Definition at line 588 of file nodeBitmapHeapscan.c.

589 {
591 
592  return ExecScan(&node->ss,
595 }
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:158
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:471
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:472
static TupleTableSlot * BitmapHeapNext(BitmapHeapScanState *node)
static bool BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
#define castNode(_type_, nodeptr)
Definition: nodes.h:197

References BitmapHeapNext(), BitmapHeapRecheck(), castNode, ExecScan(), and BitmapHeapScanState::ss.

Referenced by ExecInitBitmapHeapScan().

◆ ExecEndBitmapHeapScan()

void ExecEndBitmapHeapScan ( BitmapHeapScanState node)

Definition at line 649 of file nodeBitmapHeapscan.c.

650 {
651  TableScanDesc scanDesc;
652 
653  /*
654  * extract information from the node
655  */
656  scanDesc = node->ss.ss_currentScanDesc;
657 
658  /*
659  * Free the exprcontext
660  */
661  ExecFreeExprContext(&node->ss.ps);
662 
663  /*
664  * clear out tuple table slots
665  */
666  if (node->ss.ps.ps_ResultTupleSlot)
669 
670  /*
671  * close down subplans
672  */
674 
675  /*
676  * release bitmaps and buffers if any
677  */
678  if (node->tbmiterator)
680  if (node->prefetch_iterator)
682  if (node->tbm)
683  tbm_free(node->tbm);
684  if (node->shared_tbmiterator)
686  if (node->shared_prefetch_iterator)
688  if (node->vmbuffer != InvalidBuffer)
689  ReleaseBuffer(node->vmbuffer);
690  if (node->pvmbuffer != InvalidBuffer)
691  ReleaseBuffer(node->pvmbuffer);
692 
693  /*
694  * close heap scan
695  */
696  table_endscan(scanDesc);
697 }
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3995
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:658
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1073
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1011
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:321

References ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), InvalidBuffer, outerPlanState, BitmapHeapScanState::prefetch_iterator, ScanState::ps, PlanState::ps_ResultTupleSlot, BitmapHeapScanState::pvmbuffer, ReleaseBuffer(), BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::ss, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, table_endscan(), BitmapHeapScanState::tbm, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_free(), BitmapHeapScanState::tbmiterator, and BitmapHeapScanState::vmbuffer.

Referenced by ExecEndNode().

◆ ExecInitBitmapHeapScan()

BitmapHeapScanState* ExecInitBitmapHeapScan ( BitmapHeapScan node,
EState estate,
int  eflags 
)

Definition at line 706 of file nodeBitmapHeapscan.c.

707 {
708  BitmapHeapScanState *scanstate;
709  Relation currentRelation;
710 
711  /* check for unsupported flags */
712  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
713 
714  /*
715  * Assert caller didn't ask for an unsafe snapshot --- see comments at
716  * head of file.
717  */
719 
720  /*
721  * create state structure
722  */
723  scanstate = makeNode(BitmapHeapScanState);
724  scanstate->ss.ps.plan = (Plan *) node;
725  scanstate->ss.ps.state = estate;
726  scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
727 
728  scanstate->tbm = NULL;
729  scanstate->tbmiterator = NULL;
730  scanstate->tbmres = NULL;
731  scanstate->return_empty_tuples = 0;
732  scanstate->vmbuffer = InvalidBuffer;
733  scanstate->pvmbuffer = InvalidBuffer;
734  scanstate->exact_pages = 0;
735  scanstate->lossy_pages = 0;
736  scanstate->prefetch_iterator = NULL;
737  scanstate->prefetch_pages = 0;
738  scanstate->prefetch_target = 0;
739  scanstate->pscan_len = 0;
740  scanstate->initialized = false;
741  scanstate->shared_tbmiterator = NULL;
742  scanstate->shared_prefetch_iterator = NULL;
743  scanstate->pstate = NULL;
744 
745  /*
746  * We can potentially skip fetching heap pages if we do not need any
747  * columns of the table, either for checking non-indexable quals or for
748  * returning data. This test is a bit simplistic, as it checks the
749  * stronger condition that there's no qual or return tlist at all. But in
750  * most cases it's probably not worth working harder than that.
751  */
752  scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
753  node->scan.plan.targetlist == NIL);
754 
755  /*
756  * Miscellaneous initialization
757  *
758  * create expression context for node
759  */
760  ExecAssignExprContext(estate, &scanstate->ss.ps);
761 
762  /*
763  * open the scan relation
764  */
765  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
766 
767  /*
768  * initialize child nodes
769  */
770  outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
771 
772  /*
773  * get the scan type from the relation descriptor.
774  */
775  ExecInitScanTupleSlot(estate, &scanstate->ss,
776  RelationGetDescr(currentRelation),
777  table_slot_callbacks(currentRelation));
778 
779  /*
780  * Initialize result type and projection.
781  */
782  ExecInitResultTypeTL(&scanstate->ss.ps);
783  ExecAssignScanProjectionInfo(&scanstate->ss);
784 
785  /*
786  * initialize child expressions
787  */
788  scanstate->ss.ps.qual =
789  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
790  scanstate->bitmapqualorig =
791  ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
792 
793  /*
794  * Maximum number of prefetches for the tablespace if configured,
795  * otherwise the current value of the effective_io_concurrency GUC.
796  */
797  scanstate->prefetch_maximum =
798  get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
799 
800  scanstate->ss.ss_currentRelation = currentRelation;
801 
802  scanstate->ss.ss_currentScanDesc = table_beginscan_bm(currentRelation,
803  estate->es_snapshot,
804  0,
805  NULL);
806 
807  /*
808  * all done.
809  */
810  return scanstate;
811 }
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:213
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:272
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1811
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1755
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:488
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:728
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_MARK
Definition: executor.h:69
static TupleTableSlot * ExecBitmapHeapScan(PlanState *pstate)
#define makeNode(_type_)
Definition: nodes.h:176
#define NIL
Definition: pg_list.h:68
#define outerPlan(node)
Definition: plannodes.h:186
#define RelationGetDescr(relation)
Definition: rel.h:529
#define IsMVCCSnapshot(snapshot)
Definition: snapmgr.h:96
int get_tablespace_io_concurrency(Oid spcid)
Definition: spccache.c:215
List * bitmapqualorig
Definition: plannodes.h:542
ExprState * qual
Definition: execnodes.h:1056
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1041
Form_pg_class rd_rel
Definition: rel.h:110
Index scanrelid
Definition: plannodes.h:390
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:58
static TableScanDesc table_beginscan_bm(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:948

References Assert(), BitmapHeapScanState::bitmapqualorig, BitmapHeapScan::bitmapqualorig, BitmapHeapScanState::can_skip_fetch, EState::es_snapshot, BitmapHeapScanState::exact_pages, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecBitmapHeapScan(), ExecInitNode(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), PlanState::ExecProcNode, get_tablespace_io_concurrency(), BitmapHeapScanState::initialized, InvalidBuffer, IsMVCCSnapshot, BitmapHeapScanState::lossy_pages, makeNode, NIL, outerPlan, outerPlanState, PlanState::plan, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, BitmapHeapScanState::prefetch_pages, BitmapHeapScanState::prefetch_target, ScanState::ps, BitmapHeapScanState::pscan_len, BitmapHeapScanState::pstate, BitmapHeapScanState::pvmbuffer, PlanState::qual, RelationData::rd_rel, RelationGetDescr, BitmapHeapScanState::return_empty_tuples, BitmapHeapScan::scan, Scan::scanrelid, BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, PlanState::state, table_beginscan_bm(), table_slot_callbacks(), BitmapHeapScanState::tbm, BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, and BitmapHeapScanState::vmbuffer.

Referenced by ExecInitNode().

◆ ExecReScanBitmapHeapScan()

void ExecReScanBitmapHeapScan ( BitmapHeapScanState node)

Definition at line 602 of file nodeBitmapHeapscan.c.

603 {
605 
606  /* rescan to release any page pin */
607  table_rescan(node->ss.ss_currentScanDesc, NULL);
608 
609  /* release bitmaps and buffers if any */
610  if (node->tbmiterator)
612  if (node->prefetch_iterator)
614  if (node->shared_tbmiterator)
616  if (node->shared_prefetch_iterator)
618  if (node->tbm)
619  tbm_free(node->tbm);
620  if (node->vmbuffer != InvalidBuffer)
621  ReleaseBuffer(node->vmbuffer);
622  if (node->pvmbuffer != InvalidBuffer)
623  ReleaseBuffer(node->pvmbuffer);
624  node->tbm = NULL;
625  node->tbmiterator = NULL;
626  node->tbmres = NULL;
627  node->prefetch_iterator = NULL;
628  node->initialized = false;
629  node->shared_tbmiterator = NULL;
630  node->shared_prefetch_iterator = NULL;
631  node->vmbuffer = InvalidBuffer;
632  node->pvmbuffer = InvalidBuffer;
633 
634  ExecScanReScan(&node->ss);
635 
636  /*
637  * if chgParam of subnode is not null then plan will be re-scanned by
638  * first ExecProcNode.
639  */
640  if (outerPlan->chgParam == NULL)
642 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
void ExecScanReScan(ScanState *node)
Definition: execScan.c:299
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:1020

References ExecReScan(), ExecScanReScan(), BitmapHeapScanState::initialized, InvalidBuffer, outerPlan, outerPlanState, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::pvmbuffer, ReleaseBuffer(), BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::ss, ScanState::ss_currentScanDesc, table_rescan(), BitmapHeapScanState::tbm, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_free(), BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, and BitmapHeapScanState::vmbuffer.

Referenced by ExecReScan().