Skip to content

Commit 7f9d418

Browse files
Add common interface for TBMIterators
Add and use TBMPrivateIterator, which replaces the current TBMIterator for serial use cases, and repurpose TBMIterator to be a unified interface for both the serial ("private") and parallel ("shared") TID Bitmap iterator interfaces. This encapsulation simplifies call sites for callers supporting both parallel and serial TID Bitmap access. TBMIterator is not yet used in this commit. Author: Melanie Plageman Reviewed-by: Tomas Vondra, Heikki Linnakangas Discussion: https://postgr.es/m/063e4eb4-32d9-439e-a0b1-75565a9835a8%40iki.fi
1 parent 28328ec commit 7f9d418

File tree

10 files changed

+140
-52
lines changed

10 files changed

+140
-52
lines changed

src/backend/access/gin/ginget.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot)
373373
if (entry->matchBitmap)
374374
{
375375
if (entry->matchIterator)
376-
tbm_end_iterate(entry->matchIterator);
376+
tbm_end_private_iterate(entry->matchIterator);
377377
entry->matchIterator = NULL;
378378
tbm_free(entry->matchBitmap);
379379
entry->matchBitmap = NULL;
@@ -385,7 +385,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot)
385385

386386
if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
387387
{
388-
entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
388+
entry->matchIterator =
389+
tbm_begin_private_iterate(entry->matchBitmap);
389390
entry->isFinished = false;
390391
}
391392
}
@@ -832,12 +833,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
832833
(ItemPointerIsLossyPage(&advancePast) &&
833834
entry->matchResult->blockno == advancePastBlk))
834835
{
835-
entry->matchResult = tbm_iterate(entry->matchIterator);
836+
entry->matchResult =
837+
tbm_private_iterate(entry->matchIterator);
836838

837839
if (entry->matchResult == NULL)
838840
{
839841
ItemPointerSetInvalid(&entry->curItem);
840-
tbm_end_iterate(entry->matchIterator);
842+
tbm_end_private_iterate(entry->matchIterator);
841843
entry->matchIterator = NULL;
842844
entry->isFinished = true;
843845
break;

src/backend/access/gin/ginscan.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
246246
if (entry->list)
247247
pfree(entry->list);
248248
if (entry->matchIterator)
249-
tbm_end_iterate(entry->matchIterator);
249+
tbm_end_private_iterate(entry->matchIterator);
250250
if (entry->matchBitmap)
251251
tbm_free(entry->matchBitmap);
252252
}

src/backend/access/heap/heapam_handler.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21382138
if (scan->st.bitmap.rs_shared_iterator)
21392139
tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
21402140
else
2141-
tbmres = tbm_iterate(scan->st.bitmap.rs_iterator);
2141+
tbmres = tbm_private_iterate(scan->st.bitmap.rs_iterator);
21422142

21432143
if (tbmres == NULL)
21442144
return false;

src/backend/executor/nodeBitmapHeapscan.c

+13-12
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
9595
*/
9696
if (!node->initialized)
9797
{
98-
TBMIterator *tbmiterator = NULL;
98+
TBMPrivateIterator *tbmiterator = NULL;
9999
TBMSharedIterator *shared_tbmiterator = NULL;
100100

101101
if (!pstate)
@@ -106,12 +106,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
106106
elog(ERROR, "unrecognized result from subplan");
107107

108108
node->tbm = tbm;
109-
tbmiterator = tbm_begin_iterate(tbm);
109+
tbmiterator = tbm_begin_private_iterate(tbm);
110110

111111
#ifdef USE_PREFETCH
112112
if (node->prefetch_maximum > 0)
113113
{
114-
node->prefetch_iterator = tbm_begin_iterate(tbm);
114+
node->prefetch_iterator = tbm_begin_private_iterate(tbm);
115115
node->prefetch_pages = 0;
116116
node->prefetch_target = -1;
117117
}
@@ -332,7 +332,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
332332

333333
if (pstate == NULL)
334334
{
335-
TBMIterator *prefetch_iterator = node->prefetch_iterator;
335+
TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
336336

337337
if (node->prefetch_pages > 0)
338338
{
@@ -341,7 +341,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
341341
}
342342
else if (prefetch_iterator)
343343
{
344-
tbmpre = tbm_iterate(prefetch_iterator);
344+
tbmpre = tbm_private_iterate(prefetch_iterator);
345345
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
346346
InvalidBlockNumber;
347347
}
@@ -446,19 +446,20 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
446446

447447
if (pstate == NULL)
448448
{
449-
TBMIterator *prefetch_iterator = node->prefetch_iterator;
449+
TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
450450

451451
if (prefetch_iterator)
452452
{
453453
while (node->prefetch_pages < node->prefetch_target)
454454
{
455-
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
455+
TBMIterateResult *tbmpre;
456456
bool skip_fetch;
457457

458+
tbmpre = tbm_private_iterate(prefetch_iterator);
458459
if (tbmpre == NULL)
459460
{
460461
/* No more pages to prefetch */
461-
tbm_end_iterate(prefetch_iterator);
462+
tbm_end_private_iterate(prefetch_iterator);
462463
node->prefetch_iterator = NULL;
463464
break;
464465
}
@@ -594,7 +595,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
594595

595596
if (scan->st.bitmap.rs_iterator)
596597
{
597-
tbm_end_iterate(scan->st.bitmap.rs_iterator);
598+
tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
598599
scan->st.bitmap.rs_iterator = NULL;
599600
}
600601

@@ -604,7 +605,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
604605

605606
/* release bitmaps and buffers if any */
606607
if (node->prefetch_iterator)
607-
tbm_end_iterate(node->prefetch_iterator);
608+
tbm_end_private_iterate(node->prefetch_iterator);
608609
if (node->shared_prefetch_iterator)
609610
tbm_end_shared_iterate(node->shared_prefetch_iterator);
610611
if (node->tbm)
@@ -685,7 +686,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
685686

686687
if (scanDesc->st.bitmap.rs_iterator)
687688
{
688-
tbm_end_iterate(scanDesc->st.bitmap.rs_iterator);
689+
tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
689690
scanDesc->st.bitmap.rs_iterator = NULL;
690691
}
691692

@@ -699,7 +700,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
699700
* release bitmaps and buffers if any
700701
*/
701702
if (node->prefetch_iterator)
702-
tbm_end_iterate(node->prefetch_iterator);
703+
tbm_end_private_iterate(node->prefetch_iterator);
703704
if (node->tbm)
704705
tbm_free(node->tbm);
705706
if (node->shared_prefetch_iterator)

src/backend/nodes/tidbitmap.c

+89-25
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,12 @@ struct TIDBitmap
170170
};
171171

172172
/*
173-
* When iterating over a bitmap in sorted order, a TBMIterator is used to
174-
* track our progress. There can be several iterators scanning the same
175-
* bitmap concurrently. Note that the bitmap becomes read-only as soon as
176-
* any iterator is created.
173+
* When iterating over a backend-local bitmap in sorted order, a
174+
* TBMPrivateIterator is used to track our progress. There can be several
175+
* iterators scanning the same bitmap concurrently. Note that the bitmap
176+
* becomes read-only as soon as any iterator is created.
177177
*/
178-
struct TBMIterator
178+
struct TBMPrivateIterator
179179
{
180180
TIDBitmap *tbm; /* TIDBitmap we're iterating over */
181181
int spageptr; /* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
213213
} PTIterationArray;
214214

215215
/*
216-
* same as TBMIterator, but it is used for joint iteration, therefore this
217-
* also holds a reference to the shared state.
216+
* same as TBMPrivateIterator, but it is used for joint iteration, therefore
217+
* this also holds a reference to the shared state.
218218
*/
219219
struct TBMSharedIterator
220220
{
@@ -673,31 +673,32 @@ tbm_is_empty(const TIDBitmap *tbm)
673673
}
674674

675675
/*
676-
* tbm_begin_iterate - prepare to iterate through a TIDBitmap
676+
* tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
677677
*
678-
* The TBMIterator struct is created in the caller's memory context.
679-
* For a clean shutdown of the iteration, call tbm_end_iterate; but it's
680-
* okay to just allow the memory context to be released, too. It is caller's
681-
* responsibility not to touch the TBMIterator anymore once the TIDBitmap
682-
* is freed.
678+
* The TBMPrivateIterator struct is created in the caller's memory context.
679+
* For a clean shutdown of the iteration, call tbm_end_private_iterate; but
680+
* it's okay to just allow the memory context to be released, too. It is
681+
* caller's responsibility not to touch the TBMPrivateIterator anymore once
682+
* the TIDBitmap is freed.
683683
*
684684
* NB: after this is called, it is no longer allowed to modify the contents
685685
* of the bitmap. However, you can call this multiple times to scan the
686686
* contents repeatedly, including parallel scans.
687687
*/
688-
TBMIterator *
689-
tbm_begin_iterate(TIDBitmap *tbm)
688+
TBMPrivateIterator *
689+
tbm_begin_private_iterate(TIDBitmap *tbm)
690690
{
691-
TBMIterator *iterator;
691+
TBMPrivateIterator *iterator;
692692

693693
Assert(tbm->iterating != TBM_ITERATING_SHARED);
694694

695695
/*
696-
* Create the TBMIterator struct, with enough trailing space to serve the
697-
* needs of the TBMIterateResult sub-struct.
696+
* Create the TBMPrivateIterator struct, with enough trailing space to
697+
* serve the needs of the TBMIterateResult sub-struct.
698698
*/
699-
iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
700-
MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
699+
iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
700+
MAX_TUPLES_PER_PAGE *
701+
sizeof(OffsetNumber));
701702
iterator->tbm = tbm;
702703

703704
/*
@@ -878,7 +879,7 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
878879
ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
879880

880881
/*
881-
* For every shared iterator, referring to pagetable and iterator array,
882+
* For every shared iterator referring to pagetable and iterator array,
882883
* increase the refcount by 1 so that while freeing the shared iterator we
883884
* don't free pagetable and iterator array until its refcount becomes 0.
884885
*/
@@ -956,7 +957,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
956957
}
957958

958959
/*
959-
* tbm_iterate - scan through next page of a TIDBitmap
960+
* tbm_private_iterate - scan through next page of a TIDBitmap
960961
*
961962
* Returns a TBMIterateResult representing one page, or NULL if there are
962963
* no more pages to scan. Pages are guaranteed to be delivered in numerical
@@ -968,7 +969,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
968969
* testing, recheck is always set true when ntuples < 0.)
969970
*/
970971
TBMIterateResult *
971-
tbm_iterate(TBMIterator *iterator)
972+
tbm_private_iterate(TBMPrivateIterator *iterator)
972973
{
973974
TIDBitmap *tbm = iterator->tbm;
974975
TBMIterateResult *output = &(iterator->output);
@@ -1136,14 +1137,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
11361137
}
11371138

11381139
/*
1139-
* tbm_end_iterate - finish an iteration over a TIDBitmap
1140+
* tbm_end_private_iterate - finish an iteration over a TIDBitmap
11401141
*
11411142
* Currently this is just a pfree, but it might do more someday. (For
11421143
* instance, it could be useful to count open iterators and allow the
11431144
* bitmap to return to read/write status when there are no more iterators.)
11441145
*/
11451146
void
1146-
tbm_end_iterate(TBMIterator *iterator)
1147+
tbm_end_private_iterate(TBMPrivateIterator *iterator)
11471148
{
11481149
pfree(iterator);
11491150
}
@@ -1556,3 +1557,66 @@ tbm_calculate_entries(double maxbytes)
15561557

15571558
return nbuckets;
15581559
}
1560+
1561+
/*
1562+
* Create a shared or private bitmap iterator and start iteration.
1563+
*
1564+
* `tbm` is only used to create the private iterator and dsa and dsp are only
1565+
* used to create the shared iterator.
1566+
*
1567+
* Before invoking tbm_begin_iterate() to create a shared iterator, one
1568+
* process must already have invoked tbm_prepare_shared_iterate() to create
1569+
* and set up the TBMSharedIteratorState.
1570+
*/
1571+
TBMIterator
1572+
tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
1573+
{
1574+
TBMIterator iterator = {0};
1575+
1576+
/* Allocate a private iterator and attach the shared state to it */
1577+
if (DsaPointerIsValid(dsp))
1578+
{
1579+
iterator.shared = true;
1580+
iterator.i.shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
1581+
}
1582+
else
1583+
{
1584+
iterator.shared = false;
1585+
iterator.i.private_iterator = tbm_begin_private_iterate(tbm);
1586+
}
1587+
1588+
return iterator;
1589+
}
1590+
1591+
/*
1592+
* Clean up shared or private bitmap iterator.
1593+
*/
1594+
void
1595+
tbm_end_iterate(TBMIterator *iterator)
1596+
{
1597+
Assert(iterator);
1598+
1599+
if (iterator->shared)
1600+
tbm_end_shared_iterate(iterator->i.shared_iterator);
1601+
else
1602+
tbm_end_private_iterate(iterator->i.private_iterator);
1603+
1604+
*iterator = (TBMIterator)
1605+
{
1606+
0
1607+
};
1608+
}
1609+
1610+
/*
1611+
* Get the next TBMIterateResult from the shared or private bitmap iterator.
1612+
*/
1613+
TBMIterateResult *
1614+
tbm_iterate(TBMIterator *iterator)
1615+
{
1616+
Assert(iterator);
1617+
1618+
if (iterator->shared)
1619+
return tbm_shared_iterate(iterator->i.shared_iterator);
1620+
else
1621+
return tbm_private_iterate(iterator->i.private_iterator);
1622+
}

src/include/access/gin_private.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
352352

353353
/* for a partial-match or full-scan query, we accumulate all TIDs here */
354354
TIDBitmap *matchBitmap;
355-
TBMIterator *matchIterator;
355+
TBMPrivateIterator *matchIterator;
356356
TBMIterateResult *matchResult;
357357

358358
/* used for Posting list and one page in Posting tree */

src/include/access/relscan.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
struct ParallelTableScanDescData;
2727

28-
struct TBMIterator;
28+
struct TBMPrivateIterator;
2929
struct TBMSharedIterator;
3030

3131
/*
@@ -48,7 +48,7 @@ typedef struct TableScanDescData
4848
/* Iterators for Bitmap Table Scans */
4949
struct
5050
{
51-
struct TBMIterator *rs_iterator;
51+
struct TBMPrivateIterator *rs_iterator;
5252
struct TBMSharedIterator *rs_shared_iterator;
5353
} bitmap;
5454

src/include/nodes/execnodes.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,7 @@ typedef struct BitmapHeapScanState
18531853
TIDBitmap *tbm;
18541854
Buffer pvmbuffer;
18551855
BitmapHeapScanInstrumentation stats;
1856-
TBMIterator *prefetch_iterator;
1856+
TBMPrivateIterator *prefetch_iterator;
18571857
int prefetch_pages;
18581858
int prefetch_target;
18591859
int prefetch_maximum;

0 commit comments

Comments
 (0)