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