PostgreSQL Source Code git master
tidbitmap.h File Reference
#include "storage/itemptr.h"
#include "utils/dsa.h"
Include dependency graph for tidbitmap.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TBMIterator
 
struct  TBMIterateResult
 

Typedefs

typedef struct TIDBitmap TIDBitmap
 
typedef struct TBMPrivateIterator TBMPrivateIterator
 
typedef struct TBMSharedIterator TBMSharedIterator
 
typedef struct TBMIterator TBMIterator
 
typedef struct TBMIterateResult TBMIterateResult
 

Functions

TIDBitmaptbm_create (Size maxbytes, dsa_area *dsa)
 
void tbm_free (TIDBitmap *tbm)
 
void tbm_free_shared_area (dsa_area *dsa, dsa_pointer dp)
 
void tbm_add_tuples (TIDBitmap *tbm, const ItemPointer tids, int ntids, bool recheck)
 
void tbm_add_page (TIDBitmap *tbm, BlockNumber pageno)
 
void tbm_union (TIDBitmap *a, const TIDBitmap *b)
 
void tbm_intersect (TIDBitmap *a, const TIDBitmap *b)
 
bool tbm_is_empty (const TIDBitmap *tbm)
 
TBMPrivateIteratortbm_begin_private_iterate (TIDBitmap *tbm)
 
dsa_pointer tbm_prepare_shared_iterate (TIDBitmap *tbm)
 
TBMIterateResulttbm_private_iterate (TBMPrivateIterator *iterator)
 
TBMIterateResulttbm_shared_iterate (TBMSharedIterator *iterator)
 
void tbm_end_private_iterate (TBMPrivateIterator *iterator)
 
void tbm_end_shared_iterate (TBMSharedIterator *iterator)
 
TBMSharedIteratortbm_attach_shared_iterate (dsa_area *dsa, dsa_pointer dp)
 
int tbm_calculate_entries (Size maxbytes)
 
TBMIterator tbm_begin_iterate (TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
 
void tbm_end_iterate (TBMIterator *iterator)
 
TBMIterateResulttbm_iterate (TBMIterator *iterator)
 
static bool tbm_exhausted (TBMIterator *iterator)
 

Typedef Documentation

◆ TBMIterateResult

◆ TBMIterator

typedef struct TBMIterator TBMIterator

◆ TBMPrivateIterator

Definition at line 36 of file tidbitmap.h.

◆ TBMSharedIterator

Definition at line 37 of file tidbitmap.h.

◆ TIDBitmap

typedef struct TIDBitmap TIDBitmap

Definition at line 33 of file tidbitmap.h.

Function Documentation

◆ tbm_add_page()

void tbm_add_page ( TIDBitmap tbm,
BlockNumber  pageno 
)

Definition at line 443 of file tidbitmap.c.

444{
445 /* Enter the page in the bitmap, or mark it lossy if already present */
446 tbm_mark_page_lossy(tbm, pageno);
447 /* If we went over the memory limit, lossify some more pages */
448 if (tbm->nentries > tbm->maxentries)
449 tbm_lossify(tbm);
450}
int nentries
Definition: tidbitmap.c:155
int maxentries
Definition: tidbitmap.c:156
static void tbm_lossify(TIDBitmap *tbm)
Definition: tidbitmap.c:1356
static void tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1284

References TIDBitmap::maxentries, TIDBitmap::nentries, tbm_lossify(), and tbm_mark_page_lossy().

Referenced by bringetbitmap(), and gingetbitmap().

◆ tbm_add_tuples()

void tbm_add_tuples ( TIDBitmap tbm,
const ItemPointer  tids,
int  ntids,
bool  recheck 
)

Definition at line 377 of file tidbitmap.c.

379{
381 PagetableEntry *page = NULL; /* only valid when currblk is valid */
382 int i;
383
385 for (i = 0; i < ntids; i++)
386 {
389 int wordnum,
390 bitnum;
391
392 /* safety check to ensure we don't overrun bit array bounds */
393 if (off < 1 || off > MAX_TUPLES_PER_PAGE)
394 elog(ERROR, "tuple offset out of range: %u", off);
395
396 /*
397 * Look up target page unless we already did. This saves cycles when
398 * the input includes consecutive tuples on the same page, which is
399 * common enough to justify an extra test here.
400 */
401 if (blk != currblk)
402 {
403 if (tbm_page_is_lossy(tbm, blk))
404 page = NULL; /* remember page is lossy */
405 else
406 page = tbm_get_pageentry(tbm, blk);
407 currblk = blk;
408 }
409
410 if (page == NULL)
411 continue; /* whole page is already marked */
412
413 if (page->ischunk)
414 {
415 /* The page is a lossy chunk header, set bit for itself */
416 wordnum = bitnum = 0;
417 }
418 else
419 {
420 /* Page is exact, so set bit for individual tuple */
421 wordnum = WORDNUM(off - 1);
422 bitnum = BITNUM(off - 1);
423 }
424 page->words[wordnum] |= ((bitmapword) 1 << bitnum);
425 page->recheck |= recheck;
426
427 if (tbm->nentries > tbm->maxentries)
428 {
429 tbm_lossify(tbm);
430 /* Page could have been converted to lossy, so force new lookup */
431 currblk = InvalidBlockNumber;
432 }
433 }
434}
uint32 bitmapword
Definition: bitmapset.h:44
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
#define Assert(condition)
Definition: c.h:815
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
uint16 OffsetNumber
Definition: off.h:24
bitmapword words[Max(WORDS_PER_PAGE, WORDS_PER_CHUNK)]
Definition: tidbitmap.c:106
TBMIteratingState iterating
Definition: tidbitmap.c:159
#define MAX_TUPLES_PER_PAGE
Definition: tidbitmap.c:57
#define WORDNUM(x)
Definition: tidbitmap.c:78
@ TBM_NOT_ITERATING
Definition: tidbitmap.c:141
static bool tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1250
#define BITNUM(x)
Definition: tidbitmap.c:79
static PagetableEntry * tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1203

References Assert, BITNUM, elog, ERROR, i, InvalidBlockNumber, PagetableEntry::ischunk, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), TIDBitmap::iterating, MAX_TUPLES_PER_PAGE, TIDBitmap::maxentries, TIDBitmap::nentries, PagetableEntry::recheck, tbm_get_pageentry(), tbm_lossify(), TBM_NOT_ITERATING, tbm_page_is_lossy(), WORDNUM, and PagetableEntry::words.

Referenced by blgetbitmap(), btgetbitmap(), collectMatchBitmap(), GinDataLeafPageGetItemsToTbm(), gingetbitmap(), ginPostingListDecodeAllSegmentsToTbm(), gistScanPage(), hashgetbitmap(), scanPendingInsert(), and storeBitmap().

◆ tbm_attach_shared_iterate()

TBMSharedIterator * tbm_attach_shared_iterate ( dsa_area dsa,
dsa_pointer  dp 
)

Definition at line 1462 of file tidbitmap.c.

1463{
1464 TBMSharedIterator *iterator;
1465 TBMSharedIteratorState *istate;
1466
1467 /*
1468 * Create the TBMSharedIterator struct, with enough trailing space to
1469 * serve the needs of the TBMIterateResult sub-struct.
1470 */
1471 iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) +
1473
1474 istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
1475
1476 iterator->state = istate;
1477
1478 iterator->ptbase = dsa_get_address(dsa, istate->pagetable);
1479
1480 if (istate->npages)
1481 iterator->ptpages = dsa_get_address(dsa, istate->spages);
1482 if (istate->nchunks)
1483 iterator->ptchunks = dsa_get_address(dsa, istate->schunks);
1484
1485 return iterator;
1486}
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:942
void * palloc0(Size size)
Definition: mcxt.c:1347
dsa_pointer pagetable
Definition: tidbitmap.c:197
dsa_pointer spages
Definition: tidbitmap.c:198
dsa_pointer schunks
Definition: tidbitmap.c:199
TBMSharedIteratorState * state
Definition: tidbitmap.c:221
PTEntryArray * ptbase
Definition: tidbitmap.c:222
PTIterationArray * ptchunks
Definition: tidbitmap.c:224
PTIterationArray * ptpages
Definition: tidbitmap.c:223

References dsa_get_address(), MAX_TUPLES_PER_PAGE, TBMSharedIteratorState::nchunks, TBMSharedIteratorState::npages, TBMSharedIteratorState::pagetable, palloc0(), TBMSharedIterator::ptbase, TBMSharedIterator::ptchunks, TBMSharedIterator::ptpages, TBMSharedIteratorState::schunks, TBMSharedIteratorState::spages, and TBMSharedIterator::state.

Referenced by tbm_begin_iterate().

◆ tbm_begin_iterate()

TBMIterator tbm_begin_iterate ( TIDBitmap tbm,
dsa_area dsa,
dsa_pointer  dsp 
)

Definition at line 1572 of file tidbitmap.c.

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;
1586 }
1587
1588 return iterator;
1589}
#define DsaPointerIsValid(x)
Definition: dsa.h:106
union TBMIterator::@109 i
TBMSharedIterator * shared_iterator
Definition: tidbitmap.h:49
TBMPrivateIterator * private_iterator
Definition: tidbitmap.h:48
bool shared
Definition: tidbitmap.h:45
TBMSharedIterator * tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:1462
TBMPrivateIterator * tbm_begin_private_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:689

References DsaPointerIsValid, TBMIterator::i, TBMIterator::private_iterator, TBMIterator::shared, TBMIterator::shared_iterator, tbm_attach_shared_iterate(), and tbm_begin_private_iterate().

Referenced by BitmapTableScanSetup().

◆ tbm_begin_private_iterate()

TBMPrivateIterator * tbm_begin_private_iterate ( TIDBitmap tbm)

Definition at line 689 of file tidbitmap.c.

690{
691 TBMPrivateIterator *iterator;
692
694
695 /*
696 * Create the TBMPrivateIterator struct, with enough trailing space to
697 * serve the needs of the TBMIterateResult sub-struct.
698 */
699 iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
701 sizeof(OffsetNumber));
702 iterator->tbm = tbm;
703
704 /*
705 * Initialize iteration pointers.
706 */
707 iterator->spageptr = 0;
708 iterator->schunkptr = 0;
709 iterator->schunkbit = 0;
710
711 /*
712 * If we have a hashtable, create and fill the sorted page lists, unless
713 * we already did that for a previous iterator. Note that the lists are
714 * attached to the bitmap not the iterator, so they can be used by more
715 * than one iterator.
716 */
717 if (tbm->status == TBM_HASH && tbm->iterating == TBM_NOT_ITERATING)
718 {
719 pagetable_iterator i;
720 PagetableEntry *page;
721 int npages;
722 int nchunks;
723
724 if (!tbm->spages && tbm->npages > 0)
725 tbm->spages = (PagetableEntry **)
727 tbm->npages * sizeof(PagetableEntry *));
728 if (!tbm->schunks && tbm->nchunks > 0)
729 tbm->schunks = (PagetableEntry **)
731 tbm->nchunks * sizeof(PagetableEntry *));
732
733 npages = nchunks = 0;
734 pagetable_start_iterate(tbm->pagetable, &i);
735 while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
736 {
737 if (page->ischunk)
738 tbm->schunks[nchunks++] = page;
739 else
740 tbm->spages[npages++] = page;
741 }
742 Assert(npages == tbm->npages);
743 Assert(nchunks == tbm->nchunks);
744 if (npages > 1)
745 qsort(tbm->spages, npages, sizeof(PagetableEntry *),
747 if (nchunks > 1)
748 qsort(tbm->schunks, nchunks, sizeof(PagetableEntry *),
750 }
751
753
754 return iterator;
755}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void * palloc(Size size)
Definition: mcxt.c:1317
#define qsort(a, b, c, d)
Definition: port.h:475
TIDBitmap * tbm
Definition: tidbitmap.c:180
struct pagetable_hash * pagetable
Definition: tidbitmap.c:154
PagetableEntry ** schunks
Definition: tidbitmap.c:164
MemoryContext mcxt
Definition: tidbitmap.c:152
int npages
Definition: tidbitmap.c:157
int nchunks
Definition: tidbitmap.c:158
TBMStatus status
Definition: tidbitmap.c:153
PagetableEntry ** spages
Definition: tidbitmap.c:163
@ TBM_ITERATING_SHARED
Definition: tidbitmap.c:143
@ TBM_ITERATING_PRIVATE
Definition: tidbitmap.c:142
@ TBM_HASH
Definition: tidbitmap.c:133
static int tbm_comparator(const void *left, const void *right)
Definition: tidbitmap.c:1425

References Assert, i, PagetableEntry::ischunk, TIDBitmap::iterating, MAX_TUPLES_PER_PAGE, TIDBitmap::mcxt, MemoryContextAlloc(), TIDBitmap::nchunks, TIDBitmap::npages, TIDBitmap::pagetable, palloc(), qsort, TBMPrivateIterator::schunkbit, TBMPrivateIterator::schunkptr, TIDBitmap::schunks, TBMPrivateIterator::spageptr, TIDBitmap::spages, TIDBitmap::status, TBMPrivateIterator::tbm, tbm_comparator(), TBM_HASH, TBM_ITERATING_PRIVATE, TBM_ITERATING_SHARED, and TBM_NOT_ITERATING.

Referenced by startScanEntry(), and tbm_begin_iterate().

◆ tbm_calculate_entries()

int tbm_calculate_entries ( Size  maxbytes)

Definition at line 1543 of file tidbitmap.c.

1544{
1545 Size nbuckets;
1546
1547 /*
1548 * Estimate number of hashtable entries we can have within maxbytes. This
1549 * estimates the hash cost as sizeof(PagetableEntry), which is good enough
1550 * for our purpose. Also count an extra Pointer per entry for the arrays
1551 * created during iteration readout.
1552 */
1553 nbuckets = maxbytes /
1554 (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer));
1555 nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */
1556 nbuckets = Max(nbuckets, 16); /* sanity limit */
1557
1558 return (int) nbuckets;
1559}
#define Min(x, y)
Definition: c.h:961
#define Max(x, y)
Definition: c.h:955
char * Pointer
Definition: c.h:479
size_t Size
Definition: c.h:562
struct PagetableEntry PagetableEntry

References Max, and Min.

Referenced by compute_bitmap_pages(), and tbm_create().

◆ tbm_create()

TIDBitmap * tbm_create ( Size  maxbytes,
dsa_area dsa 
)

Definition at line 266 of file tidbitmap.c.

267{
268 TIDBitmap *tbm;
269
270 /* Create the TIDBitmap struct and zero all its fields */
271 tbm = makeNode(TIDBitmap);
272
274 tbm->status = TBM_EMPTY;
275
276 tbm->maxentries = tbm_calculate_entries(maxbytes);
277 tbm->lossify_start = 0;
278 tbm->dsa = dsa;
283
284 return tbm;
285}
#define InvalidDsaPointer
Definition: dsa.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define makeNode(_type_)
Definition: nodes.h:155
dsa_pointer ptpages
Definition: tidbitmap.c:167
dsa_pointer dsapagetableold
Definition: tidbitmap.c:166
uint32 lossify_start
Definition: tidbitmap.c:160
dsa_pointer ptchunks
Definition: tidbitmap.c:168
dsa_area * dsa
Definition: tidbitmap.c:169
dsa_pointer dsapagetable
Definition: tidbitmap.c:165
@ TBM_EMPTY
Definition: tidbitmap.c:131
int tbm_calculate_entries(Size maxbytes)
Definition: tidbitmap.c:1543

References CurrentMemoryContext, TIDBitmap::dsa, TIDBitmap::dsapagetable, TIDBitmap::dsapagetableold, InvalidDsaPointer, TIDBitmap::lossify_start, makeNode, TIDBitmap::maxentries, TIDBitmap::mcxt, TIDBitmap::ptchunks, TIDBitmap::ptpages, TIDBitmap::status, tbm_calculate_entries(), and TBM_EMPTY.

Referenced by collectMatchBitmap(), MultiExecBitmapIndexScan(), and MultiExecBitmapOr().

◆ tbm_end_iterate()

void tbm_end_iterate ( TBMIterator iterator)

Definition at line 1595 of file tidbitmap.c.

1596{
1597 Assert(iterator && !tbm_exhausted(iterator));
1598
1599 if (iterator->shared)
1601 else
1603
1604 *iterator = (TBMIterator)
1605 {
1606 0
1607 };
1608}
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1159
void tbm_end_private_iterate(TBMPrivateIterator *iterator)
Definition: tidbitmap.c:1147
struct TBMIterator TBMIterator
static bool tbm_exhausted(TBMIterator *iterator)
Definition: tidbitmap.h:96

References Assert, TBMIterator::i, TBMIterator::private_iterator, TBMIterator::shared, TBMIterator::shared_iterator, tbm_end_private_iterate(), tbm_end_shared_iterate(), and tbm_exhausted().

Referenced by BitmapPrefetch(), ExecEndBitmapHeapScan(), and ExecReScanBitmapHeapScan().

◆ tbm_end_private_iterate()

void tbm_end_private_iterate ( TBMPrivateIterator iterator)

Definition at line 1147 of file tidbitmap.c.

1148{
1149 pfree(iterator);
1150}
void pfree(void *pointer)
Definition: mcxt.c:1521

References pfree().

Referenced by entryGetItem(), ginFreeScanKeys(), startScanEntry(), and tbm_end_iterate().

◆ tbm_end_shared_iterate()

void tbm_end_shared_iterate ( TBMSharedIterator iterator)

Definition at line 1159 of file tidbitmap.c.

1160{
1161 pfree(iterator);
1162}

References pfree().

Referenced by tbm_end_iterate().

◆ tbm_exhausted()

static bool tbm_exhausted ( TBMIterator iterator)
inlinestatic

Definition at line 96 of file tidbitmap.h.

97{
98 /*
99 * It doesn't matter if we check the private or shared iterator here. If
100 * tbm_end_iterate() was called, they will be NULL
101 */
102 return !iterator->i.private_iterator;
103}

References TBMIterator::i, and TBMIterator::private_iterator.

Referenced by BitmapAdjustPrefetchIterator(), BitmapHeapNext(), BitmapPrefetch(), ExecEndBitmapHeapScan(), ExecReScanBitmapHeapScan(), and tbm_end_iterate().

◆ tbm_free()

void tbm_free ( TIDBitmap tbm)

Definition at line 322 of file tidbitmap.c.

323{
324 if (tbm->pagetable)
325 pagetable_destroy(tbm->pagetable);
326 if (tbm->spages)
327 pfree(tbm->spages);
328 if (tbm->schunks)
329 pfree(tbm->schunks);
330 pfree(tbm);
331}

References TIDBitmap::pagetable, pfree(), TIDBitmap::schunks, and TIDBitmap::spages.

Referenced by ExecEndBitmapHeapScan(), ExecReScanBitmapHeapScan(), ginFreeScanKeys(), MultiExecBitmapAnd(), MultiExecBitmapOr(), and startScanEntry().

◆ tbm_free_shared_area()

void tbm_free_shared_area ( dsa_area dsa,
dsa_pointer  dp 
)

Definition at line 341 of file tidbitmap.c.

342{
343 TBMSharedIteratorState *istate = dsa_get_address(dsa, dp);
344 PTEntryArray *ptbase;
345 PTIterationArray *ptpages;
346 PTIterationArray *ptchunks;
347
348 if (DsaPointerIsValid(istate->pagetable))
349 {
350 ptbase = dsa_get_address(dsa, istate->pagetable);
351 if (pg_atomic_sub_fetch_u32(&ptbase->refcount, 1) == 0)
352 dsa_free(dsa, istate->pagetable);
353 }
354 if (DsaPointerIsValid(istate->spages))
355 {
356 ptpages = dsa_get_address(dsa, istate->spages);
357 if (pg_atomic_sub_fetch_u32(&ptpages->refcount, 1) == 0)
358 dsa_free(dsa, istate->spages);
359 }
360 if (DsaPointerIsValid(istate->schunks))
361 {
362 ptchunks = dsa_get_address(dsa, istate->schunks);
363 if (pg_atomic_sub_fetch_u32(&ptchunks->refcount, 1) == 0)
364 dsa_free(dsa, istate->schunks);
365 }
366
367 dsa_free(dsa, dp);
368}
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition: atomics.h:439
void dsa_free(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:826
pg_atomic_uint32 refcount
Definition: tidbitmap.c:114
pg_atomic_uint32 refcount
Definition: tidbitmap.c:211

References dsa_free(), dsa_get_address(), DsaPointerIsValid, TBMSharedIteratorState::pagetable, pg_atomic_sub_fetch_u32(), PTEntryArray::refcount, PTIterationArray::refcount, TBMSharedIteratorState::schunks, and TBMSharedIteratorState::spages.

Referenced by ExecBitmapHeapReInitializeDSM().

◆ tbm_intersect()

void tbm_intersect ( TIDBitmap a,
const TIDBitmap b 
)

Definition at line 540 of file tidbitmap.c.

541{
542 Assert(!a->iterating);
543 /* Nothing to do if a is empty */
544 if (a->nentries == 0)
545 return;
546 /* Scan through chunks and pages in a, try to match to b */
547 if (a->status == TBM_ONE_PAGE)
548 {
549 if (tbm_intersect_page(a, &a->entry1, b))
550 {
551 /* Page is now empty, remove it from a */
552 Assert(!a->entry1.ischunk);
553 a->npages--;
554 a->nentries--;
555 Assert(a->nentries == 0);
556 a->status = TBM_EMPTY;
557 }
558 }
559 else
560 {
561 pagetable_iterator i;
562 PagetableEntry *apage;
563
564 Assert(a->status == TBM_HASH);
565 pagetable_start_iterate(a->pagetable, &i);
566 while ((apage = pagetable_iterate(a->pagetable, &i)) != NULL)
567 {
568 if (tbm_intersect_page(a, apage, b))
569 {
570 /* Page or chunk is now empty, remove it from a */
571 if (apage->ischunk)
572 a->nchunks--;
573 else
574 a->npages--;
575 a->nentries--;
576 if (!pagetable_delete(a->pagetable, apage->blockno))
577 elog(ERROR, "hash table corrupted");
578 }
579 }
580 }
581}
int b
Definition: isn.c:69
int a
Definition: isn.c:68
BlockNumber blockno
Definition: tidbitmap.c:102
@ TBM_ONE_PAGE
Definition: tidbitmap.c:132
static bool tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b)
Definition: tidbitmap.c:589

References a, Assert, b, PagetableEntry::blockno, elog, ERROR, i, PagetableEntry::ischunk, TBM_EMPTY, TBM_HASH, tbm_intersect_page(), and TBM_ONE_PAGE.

Referenced by MultiExecBitmapAnd().

◆ tbm_is_empty()

bool tbm_is_empty ( const TIDBitmap tbm)

Definition at line 670 of file tidbitmap.c.

671{
672 return (tbm->nentries == 0);
673}

References TIDBitmap::nentries.

Referenced by MultiExecBitmapAnd(), and startScanEntry().

◆ tbm_iterate()

TBMIterateResult * tbm_iterate ( TBMIterator iterator)

Definition at line 1614 of file tidbitmap.c.

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}
TBMIterateResult * tbm_private_iterate(TBMPrivateIterator *iterator)
Definition: tidbitmap.c:972
TBMIterateResult * tbm_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1053

References Assert, TBMIterator::i, TBMIterator::private_iterator, TBMIterator::shared, TBMIterator::shared_iterator, tbm_private_iterate(), and tbm_shared_iterate().

Referenced by BitmapAdjustPrefetchIterator(), BitmapPrefetch(), and heapam_scan_bitmap_next_block().

◆ tbm_prepare_shared_iterate()

dsa_pointer tbm_prepare_shared_iterate ( TIDBitmap tbm)

Definition at line 767 of file tidbitmap.c.

768{
769 dsa_pointer dp;
771 PTEntryArray *ptbase = NULL;
772 PTIterationArray *ptpages = NULL;
773 PTIterationArray *ptchunks = NULL;
774
775 Assert(tbm->dsa != NULL);
777
778 /*
779 * Allocate TBMSharedIteratorState from DSA to hold the shared members and
780 * lock, this will also be used by multiple worker for shared iterate.
781 */
782 dp = dsa_allocate0(tbm->dsa, sizeof(TBMSharedIteratorState));
783 istate = dsa_get_address(tbm->dsa, dp);
784
785 /*
786 * If we're not already iterating, create and fill the sorted page lists.
787 * (If we are, the sorted page lists are already stored in the TIDBitmap,
788 * and we can just reuse them.)
789 */
790 if (tbm->iterating == TBM_NOT_ITERATING)
791 {
792 pagetable_iterator i;
793 PagetableEntry *page;
794 int idx;
795 int npages;
796 int nchunks;
797
798 /*
799 * Allocate the page and chunk array memory from the DSA to share
800 * across multiple processes.
801 */
802 if (tbm->npages)
803 {
804 tbm->ptpages = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
805 tbm->npages * sizeof(int));
806 ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
807 pg_atomic_init_u32(&ptpages->refcount, 0);
808 }
809 if (tbm->nchunks)
810 {
811 tbm->ptchunks = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
812 tbm->nchunks * sizeof(int));
813 ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
814 pg_atomic_init_u32(&ptchunks->refcount, 0);
815 }
816
817 /*
818 * If TBM status is TBM_HASH then iterate over the pagetable and
819 * convert it to page and chunk arrays. But if it's in the
820 * TBM_ONE_PAGE mode then directly allocate the space for one entry
821 * from the DSA.
822 */
823 npages = nchunks = 0;
824 if (tbm->status == TBM_HASH)
825 {
826 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
827
828 pagetable_start_iterate(tbm->pagetable, &i);
829 while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
830 {
831 idx = page - ptbase->ptentry;
832 if (page->ischunk)
833 ptchunks->index[nchunks++] = idx;
834 else
835 ptpages->index[npages++] = idx;
836 }
837
838 Assert(npages == tbm->npages);
839 Assert(nchunks == tbm->nchunks);
840 }
841 else if (tbm->status == TBM_ONE_PAGE)
842 {
843 /*
844 * In one page mode allocate the space for one pagetable entry,
845 * initialize it, and directly store its index (i.e. 0) in the
846 * page array.
847 */
848 tbm->dsapagetable = dsa_allocate(tbm->dsa, sizeof(PTEntryArray) +
849 sizeof(PagetableEntry));
850 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
851 memcpy(ptbase->ptentry, &tbm->entry1, sizeof(PagetableEntry));
852 ptpages->index[0] = 0;
853 }
854
855 if (ptbase != NULL)
856 pg_atomic_init_u32(&ptbase->refcount, 0);
857 if (npages > 1)
858 qsort_arg(ptpages->index, npages, sizeof(int),
860 if (nchunks > 1)
861 qsort_arg(ptchunks->index, nchunks, sizeof(int),
863 }
864
865 /*
866 * Store the TBM members in the shared state so that we can share them
867 * across multiple processes.
868 */
869 istate->nentries = tbm->nentries;
870 istate->maxentries = tbm->maxentries;
871 istate->npages = tbm->npages;
872 istate->nchunks = tbm->nchunks;
873 istate->pagetable = tbm->dsapagetable;
874 istate->spages = tbm->ptpages;
875 istate->schunks = tbm->ptchunks;
876
877 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
878 ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
879 ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
880
881 /*
882 * For every shared iterator referring to pagetable and iterator array,
883 * increase the refcount by 1 so that while freeing the shared iterator we
884 * don't free pagetable and iterator array until its refcount becomes 0.
885 */
886 if (ptbase != NULL)
888 if (ptpages != NULL)
889 pg_atomic_add_fetch_u32(&ptpages->refcount, 1);
890 if (ptchunks != NULL)
891 pg_atomic_add_fetch_u32(&ptchunks->refcount, 1);
892
893 /* Initialize the iterator lock */
895
896 /* Initialize the shared iterator state */
897 istate->schunkbit = 0;
898 istate->schunkptr = 0;
899 istate->spageptr = 0;
900
902
903 return dp;
904}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
static uint32 pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:424
#define dsa_allocate0(area, size)
Definition: dsa.h:113
uint64 dsa_pointer
Definition: dsa.h:62
#define dsa_allocate(area, size)
Definition: dsa.h:109
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:707
@ LWTRANCHE_SHARED_TIDBITMAP
Definition: lwlock.h:200
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
PagetableEntry ptentry[FLEXIBLE_ARRAY_MEMBER]
Definition: tidbitmap.c:115
int index[FLEXIBLE_ARRAY_MEMBER]
Definition: tidbitmap.c:212
PagetableEntry entry1
Definition: tidbitmap.c:161
static int tbm_shared_comparator(const void *left, const void *right, void *arg)
Definition: tidbitmap.c:1439

References Assert, TIDBitmap::dsa, dsa_allocate, dsa_allocate0, dsa_get_address(), TIDBitmap::dsapagetable, TIDBitmap::entry1, i, idx(), PTIterationArray::index, PagetableEntry::ischunk, TIDBitmap::iterating, TBMSharedIteratorState::lock, LWLockInitialize(), LWTRANCHE_SHARED_TIDBITMAP, TIDBitmap::maxentries, TBMSharedIteratorState::maxentries, TIDBitmap::nchunks, TBMSharedIteratorState::nchunks, TIDBitmap::nentries, TBMSharedIteratorState::nentries, TIDBitmap::npages, TBMSharedIteratorState::npages, TIDBitmap::pagetable, TBMSharedIteratorState::pagetable, pg_atomic_add_fetch_u32(), pg_atomic_init_u32(), TIDBitmap::ptchunks, PTEntryArray::ptentry, TIDBitmap::ptpages, qsort_arg(), PTEntryArray::refcount, PTIterationArray::refcount, TBMSharedIteratorState::schunkbit, TBMSharedIteratorState::schunkptr, TBMSharedIteratorState::schunks, TBMSharedIteratorState::spageptr, TBMSharedIteratorState::spages, TIDBitmap::status, TBM_HASH, TBM_ITERATING_PRIVATE, TBM_ITERATING_SHARED, TBM_NOT_ITERATING, TBM_ONE_PAGE, and tbm_shared_comparator().

Referenced by BitmapTableScanSetup().

◆ tbm_private_iterate()

TBMIterateResult * tbm_private_iterate ( TBMPrivateIterator iterator)

Definition at line 972 of file tidbitmap.c.

973{
974 TIDBitmap *tbm = iterator->tbm;
975 TBMIterateResult *output = &(iterator->output);
976
978
979 /*
980 * If lossy chunk pages remain, make sure we've advanced schunkptr/
981 * schunkbit to the next set bit.
982 */
983 while (iterator->schunkptr < tbm->nchunks)
984 {
985 PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
986 int schunkbit = iterator->schunkbit;
987
988 tbm_advance_schunkbit(chunk, &schunkbit);
989 if (schunkbit < PAGES_PER_CHUNK)
990 {
991 iterator->schunkbit = schunkbit;
992 break;
993 }
994 /* advance to next chunk */
995 iterator->schunkptr++;
996 iterator->schunkbit = 0;
997 }
998
999 /*
1000 * If both chunk and per-page data remain, must output the numerically
1001 * earlier page.
1002 */
1003 if (iterator->schunkptr < tbm->nchunks)
1004 {
1005 PagetableEntry *chunk = tbm->schunks[iterator->schunkptr];
1006 BlockNumber chunk_blockno;
1007
1008 chunk_blockno = chunk->blockno + iterator->schunkbit;
1009 if (iterator->spageptr >= tbm->npages ||
1010 chunk_blockno < tbm->spages[iterator->spageptr]->blockno)
1011 {
1012 /* Return a lossy page indicator from the chunk */
1013 output->blockno = chunk_blockno;
1014 output->ntuples = -1;
1015 output->recheck = true;
1016 iterator->schunkbit++;
1017 return output;
1018 }
1019 }
1020
1021 if (iterator->spageptr < tbm->npages)
1022 {
1023 PagetableEntry *page;
1024 int ntuples;
1025
1026 /* In TBM_ONE_PAGE state, we don't allocate an spages[] array */
1027 if (tbm->status == TBM_ONE_PAGE)
1028 page = &tbm->entry1;
1029 else
1030 page = tbm->spages[iterator->spageptr];
1031
1032 /* scan bitmap to extract individual offset numbers */
1033 ntuples = tbm_extract_page_tuple(page, output);
1034 output->blockno = page->blockno;
1035 output->ntuples = ntuples;
1036 output->recheck = page->recheck;
1037 iterator->spageptr++;
1038 return output;
1039 }
1040
1041 /* Nothing more in the bitmap */
1042 return NULL;
1043}
FILE * output
TBMIterateResult output
Definition: tidbitmap.c:184
static void tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
Definition: tidbitmap.c:942
#define PAGES_PER_CHUNK
Definition: tidbitmap.c:74
static int tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output)
Definition: tidbitmap.c:912

References Assert, PagetableEntry::blockno, TIDBitmap::entry1, TIDBitmap::iterating, TIDBitmap::nchunks, TIDBitmap::npages, TBMPrivateIterator::output, output, PAGES_PER_CHUNK, PagetableEntry::recheck, TBMPrivateIterator::schunkbit, TBMPrivateIterator::schunkptr, TIDBitmap::schunks, TBMPrivateIterator::spageptr, TIDBitmap::spages, TIDBitmap::status, TBMPrivateIterator::tbm, tbm_advance_schunkbit(), tbm_extract_page_tuple(), TBM_ITERATING_PRIVATE, and TBM_ONE_PAGE.

Referenced by entryGetItem(), and tbm_iterate().

◆ tbm_shared_iterate()

TBMIterateResult * tbm_shared_iterate ( TBMSharedIterator iterator)

Definition at line 1053 of file tidbitmap.c.

1054{
1055 TBMIterateResult *output = &iterator->output;
1056 TBMSharedIteratorState *istate = iterator->state;
1057 PagetableEntry *ptbase = NULL;
1058 int *idxpages = NULL;
1059 int *idxchunks = NULL;
1060
1061 if (iterator->ptbase != NULL)
1062 ptbase = iterator->ptbase->ptentry;
1063 if (iterator->ptpages != NULL)
1064 idxpages = iterator->ptpages->index;
1065 if (iterator->ptchunks != NULL)
1066 idxchunks = iterator->ptchunks->index;
1067
1068 /* Acquire the LWLock before accessing the shared members */
1069 LWLockAcquire(&istate->lock, LW_EXCLUSIVE);
1070
1071 /*
1072 * If lossy chunk pages remain, make sure we've advanced schunkptr/
1073 * schunkbit to the next set bit.
1074 */
1075 while (istate->schunkptr < istate->nchunks)
1076 {
1077 PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
1078 int schunkbit = istate->schunkbit;
1079
1080 tbm_advance_schunkbit(chunk, &schunkbit);
1081 if (schunkbit < PAGES_PER_CHUNK)
1082 {
1083 istate->schunkbit = schunkbit;
1084 break;
1085 }
1086 /* advance to next chunk */
1087 istate->schunkptr++;
1088 istate->schunkbit = 0;
1089 }
1090
1091 /*
1092 * If both chunk and per-page data remain, must output the numerically
1093 * earlier page.
1094 */
1095 if (istate->schunkptr < istate->nchunks)
1096 {
1097 PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]];
1098 BlockNumber chunk_blockno;
1099
1100 chunk_blockno = chunk->blockno + istate->schunkbit;
1101
1102 if (istate->spageptr >= istate->npages ||
1103 chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno)
1104 {
1105 /* Return a lossy page indicator from the chunk */
1106 output->blockno = chunk_blockno;
1107 output->ntuples = -1;
1108 output->recheck = true;
1109 istate->schunkbit++;
1110
1111 LWLockRelease(&istate->lock);
1112 return output;
1113 }
1114 }
1115
1116 if (istate->spageptr < istate->npages)
1117 {
1118 PagetableEntry *page = &ptbase[idxpages[istate->spageptr]];
1119 int ntuples;
1120
1121 /* scan bitmap to extract individual offset numbers */
1122 ntuples = tbm_extract_page_tuple(page, output);
1123 output->blockno = page->blockno;
1124 output->ntuples = ntuples;
1125 output->recheck = page->recheck;
1126 istate->spageptr++;
1127
1128 LWLockRelease(&istate->lock);
1129
1130 return output;
1131 }
1132
1133 LWLockRelease(&istate->lock);
1134
1135 /* Nothing more in the bitmap */
1136 return NULL;
1137}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
TBMIterateResult output
Definition: tidbitmap.c:225

References PagetableEntry::blockno, PTIterationArray::index, TBMSharedIteratorState::lock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TBMSharedIteratorState::nchunks, TBMSharedIteratorState::npages, TBMSharedIterator::output, output, PAGES_PER_CHUNK, TBMSharedIterator::ptbase, TBMSharedIterator::ptchunks, PTEntryArray::ptentry, TBMSharedIterator::ptpages, PagetableEntry::recheck, TBMSharedIteratorState::schunkbit, TBMSharedIteratorState::schunkptr, TBMSharedIteratorState::spageptr, TBMSharedIterator::state, tbm_advance_schunkbit(), and tbm_extract_page_tuple().

Referenced by tbm_iterate().

◆ tbm_union()

void tbm_union ( TIDBitmap a,
const TIDBitmap b 
)

Definition at line 458 of file tidbitmap.c.

459{
460 Assert(!a->iterating);
461 /* Nothing to do if b is empty */
462 if (b->nentries == 0)
463 return;
464 /* Scan through chunks and pages in b, merge into a */
465 if (b->status == TBM_ONE_PAGE)
466 tbm_union_page(a, &b->entry1);
467 else
468 {
469 pagetable_iterator i;
470 PagetableEntry *bpage;
471
472 Assert(b->status == TBM_HASH);
473 pagetable_start_iterate(b->pagetable, &i);
474 while ((bpage = pagetable_iterate(b->pagetable, &i)) != NULL)
475 tbm_union_page(a, bpage);
476 }
477}
static void tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage)
Definition: tidbitmap.c:481

References a, Assert, b, i, TBM_HASH, TBM_ONE_PAGE, and tbm_union_page().

Referenced by MultiExecBitmapOr().