Age Owner Branch data TLA 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-2026, 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 "access/relscan.h"
39 : : #include "access/tableam.h"
40 : : #include "access/visibilitymap.h"
41 : : #include "executor/executor.h"
42 : : #include "executor/nodeBitmapHeapscan.h"
43 : : #include "miscadmin.h"
44 : : #include "pgstat.h"
45 : : #include "storage/bufmgr.h"
46 : : #include "utils/rel.h"
47 : : #include "utils/spccache.h"
48 : : #include "utils/wait_event.h"
49 : :
50 : : static void BitmapTableScanSetup(BitmapHeapScanState *node);
51 : : static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
52 : : static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate);
53 : : static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate);
54 : :
55 : :
56 : : /*
57 : : * Do the underlying index scan, build the bitmap, set up the parallel state
58 : : * needed for parallel workers to iterate through the bitmap, and set up the
59 : : * underlying table scan descriptor.
60 : : */
61 : : static void
409 melanieplageman@gmai 62 :CBC 12777 : BitmapTableScanSetup(BitmapHeapScanState *node)
63 : : {
64 : 12777 : TBMIterator tbmiterator = {0};
65 : 12777 : ParallelBitmapHeapState *pstate = node->pstate;
66 : 12777 : dsa_area *dsa = node->ss.ps.state->es_query_dsa;
67 : :
68 [ + + ]: 12777 : if (!pstate)
69 : : {
70 : 12606 : node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
71 : :
72 [ + - - + ]: 12606 : if (!node->tbm || !IsA(node->tbm, TIDBitmap))
409 melanieplageman@gmai 73 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
74 : : }
409 melanieplageman@gmai 75 [ + + ]:CBC 171 : else if (BitmapShouldInitializeSharedState(pstate))
76 : : {
77 : : /*
78 : : * The leader will immediately come out of the function, but others
79 : : * will be blocked until leader populates the TBM and wakes them up.
80 : : */
81 : 36 : node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
82 [ + - - + ]: 36 : if (!node->tbm || !IsA(node->tbm, TIDBitmap))
409 melanieplageman@gmai 83 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
84 : :
85 : : /*
86 : : * Prepare to iterate over the TBM. This will return the dsa_pointer
87 : : * of the iterator state which will be used by multiple processes to
88 : : * iterate jointly.
89 : : */
409 melanieplageman@gmai 90 :CBC 36 : pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm);
91 : :
92 : : /* We have initialized the shared state so wake up others. */
93 : 36 : BitmapDoneInitializingSharedState(pstate);
94 : : }
95 : :
96 [ + + ]: 12777 : tbmiterator = tbm_begin_iterate(node->tbm, dsa,
97 : : pstate ?
98 : : pstate->tbmiterator :
99 : : InvalidDsaPointer);
100 : :
101 : : /*
102 : : * If this is the first scan of the underlying table, create the table
103 : : * scan descriptor and begin the scan.
104 : : */
105 [ + + ]: 12777 : if (!node->ss.ss_currentScanDesc)
106 : : {
107 : 10672 : node->ss.ss_currentScanDesc =
108 : 10672 : table_beginscan_bm(node->ss.ss_currentRelation,
109 : 10672 : node->ss.ps.state->es_snapshot,
110 : : 0,
111 : : NULL);
112 : : }
113 : :
114 : 12777 : node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
115 : 12777 : node->initialized = true;
116 : 12777 : }
117 : :
118 : : /* ----------------------------------------------------------------
119 : : * BitmapHeapNext
120 : : *
121 : : * Retrieve next tuple from the BitmapHeapScan node's currentRelation
122 : : * ----------------------------------------------------------------
123 : : */
124 : : static TupleTableSlot *
7635 tgl@sss.pgh.pa.us 125 : 3074262 : BitmapHeapNext(BitmapHeapScanState *node)
126 : : {
365 melanieplageman@gmai 127 : 3074262 : ExprContext *econtext = node->ss.ps.ps_ExprContext;
128 : 3074262 : TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
129 : :
130 : : /*
131 : : * If we haven't yet performed the underlying index scan, do it, and begin
132 : : * the iteration over the bitmap.
133 : : */
3294 rhaas@postgresql.org 134 [ + + ]: 3074262 : if (!node->initialized)
409 melanieplageman@gmai 135 : 12777 : BitmapTableScanSetup(node);
136 : :
365 137 [ + + ]: 3453272 : while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc,
138 : : slot, &node->recheck,
139 : : &node->stats.lossy_pages,
140 : : &node->stats.exact_pages))
141 : : {
142 : : /*
143 : : * Continuing in previously obtained page.
144 : : */
145 [ + + ]: 3440689 : CHECK_FOR_INTERRUPTS();
146 : :
147 : : /*
148 : : * If we are using lossy info, we have to recheck the qual conditions
149 : : * at every tuple.
150 : : */
151 [ + + ]: 3440689 : if (node->recheck)
152 : : {
153 : 1647690 : econtext->ecxt_scantuple = slot;
154 [ + + ]: 1647690 : if (!ExecQualAndReset(node->bitmapqualorig, econtext))
155 : : {
156 : : /* Fails recheck, so drop it and loop back for another */
157 [ - + ]: 379010 : InstrCountFiltered2(node, 1);
158 : 379010 : ExecClearTuple(slot);
159 : 379010 : continue;
160 : : }
161 : : }
162 : :
163 : : /* OK to return this tuple */
164 : 3061679 : return slot;
165 : : }
166 : :
167 : : /*
168 : : * if we get here it means we are at the end of the scan..
169 : : */
7414 tgl@sss.pgh.pa.us 170 : 12580 : return ExecClearTuple(slot);
171 : : }
172 : :
173 : : /*
174 : : * BitmapDoneInitializingSharedState - Shared state is initialized
175 : : *
176 : : * By this time the leader has already populated the TBM and initialized the
177 : : * shared state so wake up other processes.
178 : : */
179 : : static inline void
3294 rhaas@postgresql.org 180 : 36 : BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
181 : : {
182 [ - + ]: 36 : SpinLockAcquire(&pstate->mutex);
183 : 36 : pstate->state = BM_FINISHED;
184 : 36 : SpinLockRelease(&pstate->mutex);
185 : 36 : ConditionVariableBroadcast(&pstate->cv);
186 : 36 : }
187 : :
188 : : /*
189 : : * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
190 : : */
191 : : static bool
5984 tgl@sss.pgh.pa.us 192 :UBC 0 : BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
193 : : {
194 : : ExprContext *econtext;
195 : :
196 : : /*
197 : : * extract necessary information from index scan node
198 : : */
199 : 0 : econtext = node->ss.ps.ps_ExprContext;
200 : :
201 : : /* Does the tuple meet the original qual conditions? */
202 : 0 : econtext->ecxt_scantuple = slot;
2967 andres@anarazel.de 203 : 0 : return ExecQualAndReset(node->bitmapqualorig, econtext);
204 : : }
205 : :
206 : : /* ----------------------------------------------------------------
207 : : * ExecBitmapHeapScan(node)
208 : : * ----------------------------------------------------------------
209 : : */
210 : : static TupleTableSlot *
3163 andres@anarazel.de 211 :CBC 2864517 : ExecBitmapHeapScan(PlanState *pstate)
212 : : {
213 : 2864517 : BitmapHeapScanState *node = castNode(BitmapHeapScanState, pstate);
214 : :
5984 tgl@sss.pgh.pa.us 215 : 2864517 : return ExecScan(&node->ss,
216 : : (ExecScanAccessMtd) BitmapHeapNext,
217 : : (ExecScanRecheckMtd) BitmapHeapRecheck);
218 : : }
219 : :
220 : : /* ----------------------------------------------------------------
221 : : * ExecReScanBitmapHeapScan(node)
222 : : * ----------------------------------------------------------------
223 : : */
224 : : void
5725 225 : 2505 : ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
226 : : {
3949 bruce@momjian.us 227 : 2505 : PlanState *outerPlan = outerPlanState(node);
228 : :
506 melanieplageman@gmai 229 : 2505 : TableScanDesc scan = node->ss.ss_currentScanDesc;
230 : :
231 [ + + ]: 2505 : if (scan)
232 : : {
233 : : /*
234 : : * End iteration on iterators saved in scan descriptor if they have
235 : : * not already been cleaned up.
236 : : */
451 237 [ + + ]: 2108 : if (!tbm_exhausted(&scan->st.rs_tbmiterator))
238 : 2105 : tbm_end_iterate(&scan->st.rs_tbmiterator);
239 : :
240 : : /* rescan to release any page pin */
708 tomas.vondra@postgre 241 : 2108 : table_rescan(node->ss.ss_currentScanDesc, NULL);
242 : : }
243 : :
244 : : /* release bitmaps and buffers if any */
7635 tgl@sss.pgh.pa.us 245 [ + + ]: 2505 : if (node->tbm)
246 : 2105 : tbm_free(node->tbm);
247 : 2505 : node->tbm = NULL;
3294 rhaas@postgresql.org 248 : 2505 : node->initialized = false;
506 melanieplageman@gmai 249 : 2505 : node->recheck = true;
250 : :
5984 tgl@sss.pgh.pa.us 251 : 2505 : ExecScanReScan(&node->ss);
252 : :
253 : : /*
254 : : * if chgParam of subnode is not null then plan will be re-scanned by
255 : : * first ExecProcNode.
256 : : */
3968 rhaas@postgresql.org 257 [ + + ]: 2505 : if (outerPlan->chgParam == NULL)
258 : 166 : ExecReScan(outerPlan);
7635 tgl@sss.pgh.pa.us 259 : 2505 : }
260 : :
261 : : /* ----------------------------------------------------------------
262 : : * ExecEndBitmapHeapScan
263 : : * ----------------------------------------------------------------
264 : : */
265 : : void
266 : 12950 : ExecEndBitmapHeapScan(BitmapHeapScanState *node)
267 : : {
268 : : TableScanDesc scanDesc;
269 : :
270 : : /*
271 : : * When ending a parallel worker, copy the statistics gathered by the
272 : : * worker back into shared memory so that it can be picked up by the main
273 : : * process to report in EXPLAIN ANALYZE.
274 : : */
614 drowley@postgresql.o 275 [ - + - - ]: 12950 : if (node->sinstrument != NULL && IsParallelWorker())
276 : : {
277 : : BitmapHeapScanInstrumentation *si;
278 : :
1 tomas.vondra@postgre 279 [ # # ]:UBC 0 : Assert(ParallelWorkerNumber < node->sinstrument->num_workers);
614 drowley@postgresql.o 280 : 0 : si = &node->sinstrument->sinstrument[ParallelWorkerNumber];
281 : :
282 : : /*
283 : : * Here we accumulate the stats rather than performing memcpy on
284 : : * node->stats into si. When a Gather/GatherMerge node finishes it
285 : : * will perform planner shutdown on the workers. On rescan it will
286 : : * spin up new workers which will have a new BitmapHeapScanState and
287 : : * zeroed stats.
288 : : */
289 : 0 : si->exact_pages += node->stats.exact_pages;
290 : 0 : si->lossy_pages += node->stats.lossy_pages;
291 : : }
292 : :
293 : : /*
294 : : * extract information from the node
295 : : */
7635 tgl@sss.pgh.pa.us 296 :CBC 12950 : scanDesc = node->ss.ss_currentScanDesc;
297 : :
298 : : /*
299 : : * close down subplans
300 : : */
301 : 12950 : ExecEndNode(outerPlanState(node));
302 : :
506 melanieplageman@gmai 303 [ + + ]: 12950 : if (scanDesc)
304 : : {
305 : : /*
306 : : * End iteration on iterators saved in scan descriptor if they have
307 : : * not already been cleaned up.
308 : : */
451 309 [ + - ]: 10615 : if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
310 : 10615 : tbm_end_iterate(&scanDesc->st.rs_tbmiterator);
311 : :
312 : : /*
313 : : * close table scan
314 : : */
506 315 : 10615 : table_endscan(scanDesc);
316 : : }
317 : :
318 : : /*
319 : : * release bitmaps and buffers if any
320 : : */
7635 tgl@sss.pgh.pa.us 321 [ + + ]: 12950 : if (node->tbm)
322 : 10480 : tbm_free(node->tbm);
323 : 12950 : }
324 : :
325 : : /* ----------------------------------------------------------------
326 : : * ExecInitBitmapHeapScan
327 : : *
328 : : * Initializes the scan's state information.
329 : : * ----------------------------------------------------------------
330 : : */
331 : : BitmapHeapScanState *
7320 332 : 13007 : ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
333 : : {
334 : : BitmapHeapScanState *scanstate;
335 : : Relation currentRelation;
336 : :
337 : : /* check for unsupported flags */
338 [ - + ]: 13007 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
339 : :
340 : : /*
341 : : * Assert caller didn't ask for an unsafe snapshot --- see comments at
342 : : * head of file.
343 : : */
7414 344 [ - + - - ]: 13007 : Assert(IsMVCCSnapshot(estate->es_snapshot));
345 : :
346 : : /*
347 : : * create state structure
348 : : */
7635 349 : 13007 : scanstate = makeNode(BitmapHeapScanState);
350 : 13007 : scanstate->ss.ps.plan = (Plan *) node;
351 : 13007 : scanstate->ss.ps.state = estate;
3163 andres@anarazel.de 352 : 13007 : scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
353 : :
7635 tgl@sss.pgh.pa.us 354 : 13007 : scanstate->tbm = NULL;
355 : :
356 : : /* Zero the statistics counters */
614 drowley@postgresql.o 357 : 13007 : memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
358 : :
3294 rhaas@postgresql.org 359 : 13007 : scanstate->initialized = false;
360 : 13007 : scanstate->pstate = NULL;
506 melanieplageman@gmai 361 : 13007 : scanstate->recheck = true;
362 : :
363 : : /*
364 : : * Miscellaneous initialization
365 : : *
366 : : * create expression context for node
367 : : */
7635 tgl@sss.pgh.pa.us 368 : 13007 : ExecAssignExprContext(estate, &scanstate->ss.ps);
369 : :
370 : : /*
371 : : * open the scan relation
372 : : */
2949 andres@anarazel.de 373 : 13007 : currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
374 : :
375 : : /*
376 : : * initialize child nodes
377 : : */
378 : 13007 : outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
379 : :
380 : : /*
381 : : * get the scan type from the relation descriptor.
382 : : */
383 : 13007 : ExecInitScanTupleSlot(estate, &scanstate->ss,
384 : : RelationGetDescr(currentRelation),
385 : : table_slot_callbacks(currentRelation));
386 : :
387 : : /*
388 : : * Initialize result type and projection.
389 : : */
2683 390 : 13007 : ExecInitResultTypeTL(&scanstate->ss.ps);
2949 391 : 13007 : ExecAssignScanProjectionInfo(&scanstate->ss);
392 : :
393 : : /*
394 : : * initialize child expressions
395 : : */
396 : 13007 : scanstate->ss.ps.qual =
397 : 13007 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
398 : 13007 : scanstate->bitmapqualorig =
399 : 13007 : ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
400 : :
7635 tgl@sss.pgh.pa.us 401 : 13007 : scanstate->ss.ss_currentRelation = currentRelation;
402 : :
403 : : /*
404 : : * all done.
405 : : */
406 : 13007 : return scanstate;
407 : : }
408 : :
409 : : /*----------------
410 : : * BitmapShouldInitializeSharedState
411 : : *
412 : : * The first process to come here and see the state to the BM_INITIAL
413 : : * will become the leader for the parallel bitmap scan and will be
414 : : * responsible for populating the TIDBitmap. The other processes will
415 : : * be blocked by the condition variable until the leader wakes them up.
416 : : * ---------------
417 : : */
418 : : static bool
3294 rhaas@postgresql.org 419 : 171 : BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
420 : : {
421 : : SharedBitmapState state;
422 : :
423 : : while (1)
424 : : {
425 [ - + ]: 195 : SpinLockAcquire(&pstate->mutex);
426 : 195 : state = pstate->state;
427 [ + + ]: 195 : if (pstate->state == BM_INITIAL)
428 : 36 : pstate->state = BM_INPROGRESS;
429 : 195 : SpinLockRelease(&pstate->mutex);
430 : :
431 : : /* Exit if bitmap is done, or if we're the leader. */
432 [ + + ]: 195 : if (state != BM_INPROGRESS)
433 : 171 : break;
434 : :
435 : : /* Wait for the leader to wake us up. */
436 : 24 : ConditionVariableSleep(&pstate->cv, WAIT_EVENT_PARALLEL_BITMAP_SCAN);
437 : : }
438 : :
439 : 171 : ConditionVariableCancelSleep();
440 : :
441 : 171 : return (state == BM_INITIAL);
442 : : }
443 : :
444 : : /* ----------------------------------------------------------------
445 : : * ExecBitmapHeapEstimate
446 : : *
447 : : * Compute the amount of space we'll need in the parallel
448 : : * query DSM, and inform pcxt->estimator about our needs.
449 : : * ----------------------------------------------------------------
450 : : */
451 : : void
452 : 9 : ExecBitmapHeapEstimate(BitmapHeapScanState *node,
453 : : ParallelContext *pcxt)
454 : : {
455 : : Size size;
456 : :
614 drowley@postgresql.o 457 : 9 : size = MAXALIGN(sizeof(ParallelBitmapHeapState));
458 : :
459 : : /* account for instrumentation, if required */
460 [ - + - - ]: 9 : if (node->ss.ps.instrument && pcxt->nworkers > 0)
461 : : {
614 drowley@postgresql.o 462 :UBC 0 : size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
463 : 0 : size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
464 : : }
465 : :
614 drowley@postgresql.o 466 :CBC 9 : shm_toc_estimate_chunk(&pcxt->estimator, size);
3294 rhaas@postgresql.org 467 : 9 : shm_toc_estimate_keys(&pcxt->estimator, 1);
468 : 9 : }
469 : :
470 : : /* ----------------------------------------------------------------
471 : : * ExecBitmapHeapInitializeDSM
472 : : *
473 : : * Set up a parallel bitmap heap scan descriptor.
474 : : * ----------------------------------------------------------------
475 : : */
476 : : void
477 : 9 : ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
478 : : ParallelContext *pcxt)
479 : : {
480 : : ParallelBitmapHeapState *pstate;
614 drowley@postgresql.o 481 : 9 : SharedBitmapHeapInstrumentation *sinstrument = NULL;
3029 rhaas@postgresql.org 482 : 9 : dsa_area *dsa = node->ss.ps.state->es_query_dsa;
483 : : char *ptr;
484 : : Size size;
485 : :
486 : : /* If there's no DSA, there are no workers; initialize nothing. */
487 [ - + ]: 9 : if (dsa == NULL)
3029 rhaas@postgresql.org 488 :UBC 0 : return;
489 : :
614 drowley@postgresql.o 490 :CBC 9 : size = MAXALIGN(sizeof(ParallelBitmapHeapState));
491 [ - + - - ]: 9 : if (node->ss.ps.instrument && pcxt->nworkers > 0)
492 : : {
614 drowley@postgresql.o 493 :UBC 0 : size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
494 : 0 : size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
495 : : }
496 : :
614 drowley@postgresql.o 497 :CBC 9 : ptr = shm_toc_allocate(pcxt->toc, size);
498 : 9 : pstate = (ParallelBitmapHeapState *) ptr;
499 : 9 : ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
500 [ - + - - ]: 9 : if (node->ss.ps.instrument && pcxt->nworkers > 0)
614 drowley@postgresql.o 501 :UBC 0 : sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
502 : :
3294 rhaas@postgresql.org 503 :CBC 9 : pstate->tbmiterator = 0;
504 : :
505 : : /* Initialize the mutex */
506 : 9 : SpinLockInit(&pstate->mutex);
507 : 9 : pstate->state = BM_INITIAL;
508 : :
509 : 9 : ConditionVariableInit(&pstate->cv);
510 : :
614 drowley@postgresql.o 511 [ - + ]: 9 : if (sinstrument)
512 : : {
614 drowley@postgresql.o 513 :UBC 0 : sinstrument->num_workers = pcxt->nworkers;
514 : :
515 : : /* ensure any unfilled slots will contain zeroes */
516 : 0 : memset(sinstrument->sinstrument, 0,
517 : 0 : pcxt->nworkers * sizeof(BitmapHeapScanInstrumentation));
518 : : }
519 : :
3294 rhaas@postgresql.org 520 :CBC 9 : shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
521 : 9 : node->pstate = pstate;
614 drowley@postgresql.o 522 : 9 : node->sinstrument = sinstrument;
523 : : }
524 : :
525 : : /* ----------------------------------------------------------------
526 : : * ExecBitmapHeapReInitializeDSM
527 : : *
528 : : * Reset shared state before beginning a fresh scan.
529 : : * ----------------------------------------------------------------
530 : : */
531 : : void
3119 tgl@sss.pgh.pa.us 532 : 27 : ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
533 : : ParallelContext *pcxt)
534 : : {
535 : 27 : ParallelBitmapHeapState *pstate = node->pstate;
536 : 27 : dsa_area *dsa = node->ss.ps.state->es_query_dsa;
537 : :
538 : : /* If there's no DSA, there are no workers; do nothing. */
3029 rhaas@postgresql.org 539 [ - + ]: 27 : if (dsa == NULL)
3029 rhaas@postgresql.org 540 :UBC 0 : return;
541 : :
3119 tgl@sss.pgh.pa.us 542 :CBC 27 : pstate->state = BM_INITIAL;
543 : :
544 [ + - ]: 27 : if (DsaPointerIsValid(pstate->tbmiterator))
545 : 27 : tbm_free_shared_area(dsa, pstate->tbmiterator);
546 : :
547 : 27 : pstate->tbmiterator = InvalidDsaPointer;
548 : : }
549 : :
550 : : /* ----------------------------------------------------------------
551 : : * ExecBitmapHeapInitializeWorker
552 : : *
553 : : * Copy relevant information from TOC into planstate.
554 : : * ----------------------------------------------------------------
555 : : */
556 : : void
3041 andres@anarazel.de 557 : 135 : ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
558 : : ParallelWorkerContext *pwcxt)
559 : : {
560 : : char *ptr;
561 : :
3029 rhaas@postgresql.org 562 [ - + ]: 135 : Assert(node->ss.ps.state->es_query_dsa != NULL);
563 : :
614 drowley@postgresql.o 564 : 135 : ptr = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
565 : :
566 : 135 : node->pstate = (ParallelBitmapHeapState *) ptr;
567 : 135 : ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
568 : :
569 [ - + ]: 135 : if (node->ss.ps.instrument)
614 drowley@postgresql.o 570 :UBC 0 : node->sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
614 drowley@postgresql.o 571 :CBC 135 : }
572 : :
573 : : /* ----------------------------------------------------------------
574 : : * ExecBitmapHeapRetrieveInstrumentation
575 : : *
576 : : * Transfer bitmap heap scan statistics from DSM to private memory.
577 : : * ----------------------------------------------------------------
578 : : */
579 : : void
614 drowley@postgresql.o 580 :UBC 0 : ExecBitmapHeapRetrieveInstrumentation(BitmapHeapScanState *node)
581 : : {
582 : 0 : SharedBitmapHeapInstrumentation *sinstrument = node->sinstrument;
583 : : Size size;
584 : :
585 [ # # ]: 0 : if (sinstrument == NULL)
586 : 0 : return;
587 : :
588 : 0 : size = offsetof(SharedBitmapHeapInstrumentation, sinstrument)
589 : 0 : + sinstrument->num_workers * sizeof(BitmapHeapScanInstrumentation);
590 : :
591 : 0 : node->sinstrument = palloc(size);
592 : 0 : memcpy(node->sinstrument, sinstrument, size);
593 : : }
|