Skip to content

Commit 944e81b

Browse files
Separate TBM[Shared|Private]Iterator and TBMIterateResult
Remove the TBMIterateResult member from the TBMPrivateIterator and TBMSharedIterator and make tbm_[shared|private_]iterate() take a TBMIterateResult as a parameter. This allows tidbitmap API users to manage multiple TBMIterateResults per scan. This is required for bitmap heap scan to use the read stream API, with which there may be multiple I/Os in flight at once, each one with a TBMIterateResult. Reviewed-by: Tomas Vondra <tomas@vondra.me> Discussion: https://postgr.es/m/d4bb26c9-fe07-439e-ac53-c0e244387e01%40vondra.me
1 parent 799959d commit 944e81b

File tree

7 files changed

+110
-101
lines changed

7 files changed

+110
-101
lines changed

src/backend/access/gin/ginget.c

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot)
332332
entry->list = NULL;
333333
entry->nlist = 0;
334334
entry->matchBitmap = NULL;
335-
entry->matchResult = NULL;
336335
entry->matchNtuples = -1;
336+
entry->matchResult.blockno = InvalidBlockNumber;
337337
entry->reduceResult = false;
338338
entry->predictNumberResult = 0;
339339

@@ -827,20 +827,19 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
827827
{
828828
/*
829829
* If we've exhausted all items on this block, move to next block
830-
* in the bitmap.
830+
* in the bitmap. tbm_private_iterate() sets matchResult.blockno
831+
* to InvalidBlockNumber when the bitmap is exhausted.
831832
*/
832-
while (entry->matchResult == NULL ||
833-
(!entry->matchResult->lossy &&
833+
while ((!BlockNumberIsValid(entry->matchResult.blockno)) ||
834+
(!entry->matchResult.lossy &&
834835
entry->offset >= entry->matchNtuples) ||
835-
entry->matchResult->blockno < advancePastBlk ||
836+
entry->matchResult.blockno < advancePastBlk ||
836837
(ItemPointerIsLossyPage(&advancePast) &&
837-
entry->matchResult->blockno == advancePastBlk))
838+
entry->matchResult.blockno == advancePastBlk))
838839
{
839-
entry->matchResult =
840-
tbm_private_iterate(entry->matchIterator);
841-
842-
if (entry->matchResult == NULL)
840+
if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult))
843841
{
842+
Assert(!BlockNumberIsValid(entry->matchResult.blockno));
844843
ItemPointerSetInvalid(&entry->curItem);
845844
tbm_end_private_iterate(entry->matchIterator);
846845
entry->matchIterator = NULL;
@@ -849,14 +848,14 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
849848
}
850849

851850
/* Exact pages need their tuple offsets extracted. */
852-
if (!entry->matchResult->lossy)
853-
entry->matchNtuples = tbm_extract_page_tuple(entry->matchResult,
851+
if (!entry->matchResult.lossy)
852+
entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult,
854853
entry->matchOffsets,
855854
TBM_MAX_TUPLES_PER_PAGE);
856855

857856
/*
858857
* Reset counter to the beginning of entry->matchResult. Note:
859-
* entry->offset is still greater than entry->matchNtuples if
858+
* entry->offset is still greater than matchResult.ntuples if
860859
* matchResult is lossy. So, on next call we will get next
861860
* result from TIDBitmap.
862861
*/
@@ -869,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
869868
* We're now on the first page after advancePast which has any
870869
* items on it. If it's a lossy result, return that.
871870
*/
872-
if (entry->matchResult->lossy)
871+
if (entry->matchResult.lossy)
873872
{
874873
ItemPointerSetLossyPage(&entry->curItem,
875-
entry->matchResult->blockno);
874+
entry->matchResult.blockno);
876875

877876
/*
878877
* We might as well fall out of the loop; we could not
@@ -889,7 +888,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
889888
Assert(entry->matchNtuples > -1);
890889

891890
/* Skip over any offsets <= advancePast, and return that. */
892-
if (entry->matchResult->blockno == advancePastBlk)
891+
if (entry->matchResult.blockno == advancePastBlk)
893892
{
894893
Assert(entry->matchNtuples > 0);
895894

@@ -910,7 +909,7 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
910909
}
911910

912911
ItemPointerSet(&entry->curItem,
913-
entry->matchResult->blockno,
912+
entry->matchResult.blockno,
914913
entry->matchOffsets[entry->offset]);
915914
entry->offset++;
916915

src/backend/access/gin/ginscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
111111
ItemPointerSetMin(&scanEntry->curItem);
112112
scanEntry->matchBitmap = NULL;
113113
scanEntry->matchIterator = NULL;
114-
scanEntry->matchResult = NULL;
114+
scanEntry->matchResult.blockno = InvalidBlockNumber;
115115
scanEntry->matchNtuples = -1;
116116
scanEntry->list = NULL;
117117
scanEntry->nlist = 0;

src/backend/access/heap/heapam_handler.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,7 +2126,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21262126
Buffer buffer;
21272127
Snapshot snapshot;
21282128
int ntup;
2129-
TBMIterateResult *tbmres;
2129+
TBMIterateResult tbmres;
21302130
OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE];
21312131
int noffsets = -1;
21322132

@@ -2142,14 +2142,12 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21422142
{
21432143
CHECK_FOR_INTERRUPTS();
21442144

2145-
tbmres = tbm_iterate(&scan->st.rs_tbmiterator);
2146-
2147-
if (tbmres == NULL)
2145+
if (!tbm_iterate(&scan->st.rs_tbmiterator, &tbmres))
21482146
return false;
21492147

21502148
/* Exact pages need their tuple offsets extracted. */
2151-
if (!tbmres->lossy)
2152-
noffsets = tbm_extract_page_tuple(tbmres, offsets,
2149+
if (!tbmres.lossy)
2150+
noffsets = tbm_extract_page_tuple(&tbmres, offsets,
21532151
TBM_MAX_TUPLES_PER_PAGE);
21542152

21552153
/*
@@ -2161,23 +2159,23 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21612159
* reachable by the index.
21622160
*/
21632161
} while (!IsolationIsSerializable() &&
2164-
tbmres->blockno >= hscan->rs_nblocks);
2162+
tbmres.blockno >= hscan->rs_nblocks);
21652163

21662164
/* Got a valid block */
2167-
*blockno = tbmres->blockno;
2168-
*recheck = tbmres->recheck;
2165+
*blockno = tbmres.blockno;
2166+
*recheck = tbmres.recheck;
21692167

21702168
/*
21712169
* We can skip fetching the heap page if we don't need any fields from the
21722170
* heap, the bitmap entries don't need rechecking, and all tuples on the
21732171
* page are visible to our transaction.
21742172
*/
21752173
if (!(scan->rs_flags & SO_NEED_TUPLES) &&
2176-
!tbmres->recheck &&
2177-
VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &bscan->rs_vmbuffer))
2174+
!tbmres.recheck &&
2175+
VM_ALL_VISIBLE(scan->rs_rd, tbmres.blockno, &bscan->rs_vmbuffer))
21782176
{
21792177
/* can't be lossy in the skip_fetch case */
2180-
Assert(!tbmres->lossy);
2178+
Assert(!tbmres.lossy);
21812179
Assert(bscan->rs_empty_tuples_pending >= 0);
21822180
Assert(noffsets > -1);
21832181

@@ -2186,7 +2184,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
21862184
return true;
21872185
}
21882186

2189-
block = tbmres->blockno;
2187+
block = tbmres.blockno;
21902188

21912189
/*
21922190
* Acquire pin on the target heap page, trading in any pin we held before.
@@ -2215,7 +2213,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
22152213
/*
22162214
* We need two separate strategies for lossy and non-lossy cases.
22172215
*/
2218-
if (!tbmres->lossy)
2216+
if (!tbmres.lossy)
22192217
{
22202218
/*
22212219
* Bitmap is non-lossy, so we just look through the offsets listed in
@@ -2279,7 +2277,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
22792277
Assert(ntup <= MaxHeapTuplesPerPage);
22802278
hscan->rs_ntuples = ntup;
22812279

2282-
if (tbmres->lossy)
2280+
if (tbmres.lossy)
22832281
(*lossy_pages)++;
22842282
else
22852283
(*exact_pages)++;

src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
317317
{
318318
#ifdef USE_PREFETCH
319319
ParallelBitmapHeapState *pstate = node->pstate;
320-
TBMIterateResult *tbmpre;
320+
TBMIterateResult tbmpre;
321321

322322
if (pstate == NULL)
323323
{
@@ -330,9 +330,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
330330
}
331331
else if (!tbm_exhausted(prefetch_iterator))
332332
{
333-
tbmpre = tbm_iterate(prefetch_iterator);
334-
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
335-
InvalidBlockNumber;
333+
tbm_iterate(prefetch_iterator, &tbmpre);
334+
node->prefetch_blockno = tbmpre.blockno;
336335
}
337336
return;
338337
}
@@ -371,9 +370,8 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
371370
*/
372371
if (!tbm_exhausted(prefetch_iterator))
373372
{
374-
tbmpre = tbm_iterate(prefetch_iterator);
375-
node->prefetch_blockno = tbmpre ? tbmpre->blockno :
376-
InvalidBlockNumber;
373+
tbm_iterate(prefetch_iterator, &tbmpre);
374+
node->prefetch_blockno = tbmpre.blockno;
377375
}
378376
}
379377
}
@@ -441,17 +439,18 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
441439
{
442440
while (node->prefetch_pages < node->prefetch_target)
443441
{
444-
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
442+
TBMIterateResult tbmpre;
445443
bool skip_fetch;
446444

447-
if (tbmpre == NULL)
445+
if (!tbm_iterate(prefetch_iterator, &tbmpre))
448446
{
449447
/* No more pages to prefetch */
448+
Assert(!BlockNumberIsValid(tbmpre.blockno));
450449
tbm_end_iterate(prefetch_iterator);
451450
break;
452451
}
453452
node->prefetch_pages++;
454-
node->prefetch_blockno = tbmpre->blockno;
453+
node->prefetch_blockno = tbmpre.blockno;
455454

456455
/*
457456
* If we expect not to have to actually read this heap page,
@@ -460,13 +459,13 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
460459
* prefetch_pages?)
461460
*/
462461
skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
463-
!tbmpre->recheck &&
462+
!tbmpre.recheck &&
464463
VM_ALL_VISIBLE(node->ss.ss_currentRelation,
465-
tbmpre->blockno,
464+
tbmpre.blockno,
466465
&node->pvmbuffer));
467466

468467
if (!skip_fetch)
469-
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
468+
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
470469
}
471470
}
472471

@@ -481,7 +480,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
481480
{
482481
while (1)
483482
{
484-
TBMIterateResult *tbmpre;
483+
TBMIterateResult tbmpre;
485484
bool do_prefetch = false;
486485
bool skip_fetch;
487486

@@ -500,25 +499,25 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
500499
if (!do_prefetch)
501500
return;
502501

503-
tbmpre = tbm_iterate(prefetch_iterator);
504-
if (tbmpre == NULL)
502+
if (!tbm_iterate(prefetch_iterator, &tbmpre))
505503
{
504+
Assert(!BlockNumberIsValid(tbmpre.blockno));
506505
/* No more pages to prefetch */
507506
tbm_end_iterate(prefetch_iterator);
508507
break;
509508
}
510509

511-
node->prefetch_blockno = tbmpre->blockno;
510+
node->prefetch_blockno = tbmpre.blockno;
512511

513512
/* As above, skip prefetch if we expect not to need page */
514513
skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) &&
515-
!tbmpre->recheck &&
514+
!tbmpre.recheck &&
516515
VM_ALL_VISIBLE(node->ss.ss_currentRelation,
517-
tbmpre->blockno,
516+
tbmpre.blockno,
518517
&node->pvmbuffer));
519518

520519
if (!skip_fetch)
521-
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
520+
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre.blockno);
522521
}
523522
}
524523
}

0 commit comments

Comments
 (0)