mirror of
https://github.com/postgres/postgres.git
synced 2025-11-18 02:02:55 +03:00
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
This commit is contained in:
@@ -172,7 +172,6 @@ struct TBMPrivateIterator
|
||||
int spageptr; /* next spages index */
|
||||
int schunkptr; /* next schunks index */
|
||||
int schunkbit; /* next bit to check in current schunk */
|
||||
TBMIterateResult output;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -213,7 +212,6 @@ struct TBMSharedIterator
|
||||
PTEntryArray *ptbase; /* pagetable element array */
|
||||
PTIterationArray *ptpages; /* sorted exact page index list */
|
||||
PTIterationArray *ptchunks; /* sorted lossy page index list */
|
||||
TBMIterateResult output;
|
||||
};
|
||||
|
||||
/* Local function prototypes */
|
||||
@@ -957,21 +955,28 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
|
||||
/*
|
||||
* tbm_private_iterate - scan through next page of a TIDBitmap
|
||||
*
|
||||
* Returns a TBMIterateResult representing one page, or NULL if there are
|
||||
* no more pages to scan. Pages are guaranteed to be delivered in numerical
|
||||
* order. If lossy is true, then the bitmap is "lossy" and failed to
|
||||
* remember the exact tuples to look at on this page --- the caller must
|
||||
* examine all tuples on the page and check if they meet the intended
|
||||
* condition. result->ntuples is set to -1 when the bitmap is lossy.
|
||||
* If result->recheck is true, only the indicated tuples need
|
||||
* be examined, but the condition must be rechecked anyway. (For ease of
|
||||
* testing, recheck is always set true when lossy is true.)
|
||||
* Caller must pass in a TBMIterateResult to be filled.
|
||||
*
|
||||
* Pages are guaranteed to be delivered in numerical order.
|
||||
*
|
||||
* Returns false when there are no more pages to scan and true otherwise. When
|
||||
* there are no more pages to scan, tbmres->blockno is set to
|
||||
* InvalidBlockNumber.
|
||||
*
|
||||
* If lossy is true, then the bitmap is "lossy" and failed to remember
|
||||
* the exact tuples to look at on this page --- the caller must examine all
|
||||
* tuples on the page and check if they meet the intended condition. If lossy
|
||||
* is false, the caller must later extract the tuple offsets from the page
|
||||
* pointed to by internal_page with tbm_extract_page_tuple.
|
||||
*
|
||||
* If tbmres->recheck is true, only the indicated tuples need be examined, but
|
||||
* the condition must be rechecked anyway. (For ease of testing, recheck is
|
||||
* always set true when lossy is true.)
|
||||
*/
|
||||
TBMIterateResult *
|
||||
tbm_private_iterate(TBMPrivateIterator *iterator)
|
||||
bool
|
||||
tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
|
||||
{
|
||||
TIDBitmap *tbm = iterator->tbm;
|
||||
TBMIterateResult *output = &(iterator->output);
|
||||
|
||||
Assert(tbm->iterating == TBM_ITERATING_PRIVATE);
|
||||
|
||||
@@ -1009,12 +1014,12 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
|
||||
chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
|
||||
{
|
||||
/* Return a lossy page indicator from the chunk */
|
||||
output->blockno = chunk_blockno;
|
||||
output->lossy = true;
|
||||
output->recheck = true;
|
||||
output->internal_page = NULL;
|
||||
tbmres->blockno = chunk_blockno;
|
||||
tbmres->lossy = true;
|
||||
tbmres->recheck = true;
|
||||
tbmres->internal_page = NULL;
|
||||
iterator->schunkbit++;
|
||||
return output;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1028,16 +1033,17 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
|
||||
else
|
||||
page = tbm->spages[iterator->spageptr];
|
||||
|
||||
output->internal_page = page;
|
||||
output->blockno = page->blockno;
|
||||
output->lossy = false;
|
||||
output->recheck = page->recheck;
|
||||
tbmres->internal_page = page;
|
||||
tbmres->blockno = page->blockno;
|
||||
tbmres->lossy = false;
|
||||
tbmres->recheck = page->recheck;
|
||||
iterator->spageptr++;
|
||||
return output;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Nothing more in the bitmap */
|
||||
return NULL;
|
||||
tbmres->blockno = InvalidBlockNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1047,10 +1053,9 @@ tbm_private_iterate(TBMPrivateIterator *iterator)
|
||||
* across multiple processes. We need to acquire the iterator LWLock,
|
||||
* before accessing the shared members.
|
||||
*/
|
||||
TBMIterateResult *
|
||||
tbm_shared_iterate(TBMSharedIterator *iterator)
|
||||
bool
|
||||
tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
|
||||
{
|
||||
TBMIterateResult *output = &iterator->output;
|
||||
TBMSharedIteratorState *istate = iterator->state;
|
||||
PagetableEntry *ptbase = NULL;
|
||||
int *idxpages = NULL;
|
||||
@@ -1101,14 +1106,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
|
||||
chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
|
||||
{
|
||||
/* Return a lossy page indicator from the chunk */
|
||||
output->blockno = chunk_blockno;
|
||||
output->lossy = true;
|
||||
output->recheck = true;
|
||||
output->internal_page = NULL;
|
||||
tbmres->blockno = chunk_blockno;
|
||||
tbmres->lossy = true;
|
||||
tbmres->recheck = true;
|
||||
tbmres->internal_page = NULL;
|
||||
istate->schunkbit++;
|
||||
|
||||
LWLockRelease(&istate->lock);
|
||||
return output;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1116,21 +1121,22 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
|
||||
{
|
||||
PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
|
||||
|
||||
output->internal_page = page;
|
||||
output->blockno = page->blockno;
|
||||
output->lossy = false;
|
||||
output->recheck = page->recheck;
|
||||
tbmres->internal_page = page;
|
||||
tbmres->blockno = page->blockno;
|
||||
tbmres->lossy = false;
|
||||
tbmres->recheck = page->recheck;
|
||||
istate->spageptr++;
|
||||
|
||||
LWLockRelease(&istate->lock);
|
||||
|
||||
return output;
|
||||
return true;
|
||||
}
|
||||
|
||||
LWLockRelease(&istate->lock);
|
||||
|
||||
/* Nothing more in the bitmap */
|
||||
return NULL;
|
||||
tbmres->blockno = InvalidBlockNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1604,15 +1610,17 @@ tbm_end_iterate(TBMIterator *iterator)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next TBMIterateResult from the shared or private bitmap iterator.
|
||||
* Populate the next TBMIterateResult using the shared or private bitmap
|
||||
* iterator. Returns false when there is nothing more to scan.
|
||||
*/
|
||||
TBMIterateResult *
|
||||
tbm_iterate(TBMIterator *iterator)
|
||||
bool
|
||||
tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres)
|
||||
{
|
||||
Assert(iterator);
|
||||
Assert(tbmres);
|
||||
|
||||
if (iterator->shared)
|
||||
return tbm_shared_iterate(iterator->i.shared_iterator);
|
||||
return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
|
||||
else
|
||||
return tbm_private_iterate(iterator->i.private_iterator);
|
||||
return tbm_private_iterate(iterator->i.private_iterator, tbmres);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user