PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tidbitmap.h File Reference
#include "access/htup_details.h"
#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
 

Macros

#define TBM_MAX_TUPLES_PER_PAGE   MaxHeapTuplesPerPage
 

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)
 
int tbm_extract_page_tuple (TBMIterateResult *iteritem, OffsetNumber *offsets, uint32 max_offsets)
 
bool tbm_is_empty (const TIDBitmap *tbm)
 
TBMPrivateIteratortbm_begin_private_iterate (TIDBitmap *tbm)
 
dsa_pointer tbm_prepare_shared_iterate (TIDBitmap *tbm)
 
bool tbm_private_iterate (TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
 
bool tbm_shared_iterate (TBMSharedIterator *iterator, TBMIterateResult *tbmres)
 
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)
 
bool tbm_iterate (TBMIterator *iterator, TBMIterateResult *tbmres)
 
static bool tbm_exhausted (TBMIterator *iterator)
 

Macro Definition Documentation

◆ TBM_MAX_TUPLES_PER_PAGE

#define TBM_MAX_TUPLES_PER_PAGE   MaxHeapTuplesPerPage

Definition at line 35 of file tidbitmap.h.

Typedef Documentation

◆ TBMIterateResult

◆ TBMIterator

typedef struct TBMIterator TBMIterator

◆ TBMPrivateIterator

Definition at line 44 of file tidbitmap.h.

◆ TBMSharedIterator

Definition at line 45 of file tidbitmap.h.

◆ TIDBitmap

typedef struct TIDBitmap TIDBitmap

Definition at line 41 of file tidbitmap.h.

Function Documentation

◆ tbm_add_page()

void tbm_add_page ( TIDBitmap tbm,
BlockNumber  pageno 
)

Definition at line 432 of file tidbitmap.c.

433{
434 /* Enter the page in the bitmap, or mark it lossy if already present */
435 tbm_mark_page_lossy(tbm, pageno);
436 /* If we went over the memory limit, lossify some more pages */
437 if (tbm->nentries > tbm->maxentries)
438 tbm_lossify(tbm);
439}
int nentries
Definition: tidbitmap.c:146
int maxentries
Definition: tidbitmap.c:147
static void tbm_lossify(TIDBitmap *tbm)
Definition: tidbitmap.c:1359
static void tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1287

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 366 of file tidbitmap.c.

368{
370 PagetableEntry *page = NULL; /* only valid when currblk is valid */
371 int i;
372
374 for (i = 0; i < ntids; i++)
375 {
378 int wordnum,
379 bitnum;
380
381 /* safety check to ensure we don't overrun bit array bounds */
382 if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE)
383 elog(ERROR, "tuple offset out of range: %u", off);
384
385 /*
386 * Look up target page unless we already did. This saves cycles when
387 * the input includes consecutive tuples on the same page, which is
388 * common enough to justify an extra test here.
389 */
390 if (blk != currblk)
391 {
392 if (tbm_page_is_lossy(tbm, blk))
393 page = NULL; /* remember page is lossy */
394 else
395 page = tbm_get_pageentry(tbm, blk);
396 currblk = blk;
397 }
398
399 if (page == NULL)
400 continue; /* whole page is already marked */
401
402 if (page->ischunk)
403 {
404 /* The page is a lossy chunk header, set bit for itself */
405 wordnum = bitnum = 0;
406 }
407 else
408 {
409 /* Page is exact, so set bit for individual tuple */
410 wordnum = WORDNUM(off - 1);
411 bitnum = BITNUM(off - 1);
412 }
413 page->words[wordnum] |= ((bitmapword) 1 << bitnum);
414 page->recheck |= recheck;
415
416 if (tbm->nentries > tbm->maxentries)
417 {
418 tbm_lossify(tbm);
419 /* Page could have been converted to lossy, so force new lookup */
420 currblk = InvalidBlockNumber;
421 }
422 }
423}
uint32 bitmapword
Definition: bitmapset.h:44
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
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:97
TBMIteratingState iterating
Definition: tidbitmap.c:150
#define WORDNUM(x)
Definition: tidbitmap.c:69
@ TBM_NOT_ITERATING
Definition: tidbitmap.c:132
static bool tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1253
#define BITNUM(x)
Definition: tidbitmap.c:70
static PagetableEntry * tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:1206
#define TBM_MAX_TUPLES_PER_PAGE
Definition: tidbitmap.h:35

References Assert(), BITNUM, elog, ERROR, i, InvalidBlockNumber, PagetableEntry::ischunk, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), TIDBitmap::iterating, TIDBitmap::maxentries, TIDBitmap::nentries, PagetableEntry::recheck, tbm_get_pageentry(), tbm_lossify(), TBM_MAX_TUPLES_PER_PAGE, 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 1465 of file tidbitmap.c.

1466{
1467 TBMSharedIterator *iterator;
1468 TBMSharedIteratorState *istate;
1469
1470 /*
1471 * Create the TBMSharedIterator struct, with enough trailing space to
1472 * serve the needs of the TBMIterateResult sub-struct.
1473 */
1474 iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator));
1475
1476 istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp);
1477
1478 iterator->state = istate;
1479
1480 iterator->ptbase = dsa_get_address(dsa, istate->pagetable);
1481
1482 if (istate->npages)
1483 iterator->ptpages = dsa_get_address(dsa, istate->spages);
1484 if (istate->nchunks)
1485 iterator->ptchunks = dsa_get_address(dsa, istate->schunks);
1486
1487 return iterator;
1488}
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:942
void * palloc0(Size size)
Definition: mcxt.c:1969
dsa_pointer pagetable
Definition: tidbitmap.c:187
dsa_pointer spages
Definition: tidbitmap.c:188
dsa_pointer schunks
Definition: tidbitmap.c:189
TBMSharedIteratorState * state
Definition: tidbitmap.c:211
PTEntryArray * ptbase
Definition: tidbitmap.c:212
PTIterationArray * ptchunks
Definition: tidbitmap.c:214
PTIterationArray * ptpages
Definition: tidbitmap.c:213

References dsa_get_address(), 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 1574 of file tidbitmap.c.

1575{
1576 TBMIterator iterator = {0};
1577
1578 /* Allocate a private iterator and attach the shared state to it */
1579 if (DsaPointerIsValid(dsp))
1580 {
1581 iterator.shared = true;
1582 iterator.i.shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
1583 }
1584 else
1585 {
1586 iterator.shared = false;
1588 }
1589
1590 return iterator;
1591}
#define DsaPointerIsValid(x)
Definition: dsa.h:106
union TBMIterator::@109 i
TBMSharedIterator * shared_iterator
Definition: tidbitmap.h:57
TBMPrivateIterator * private_iterator
Definition: tidbitmap.h:56
bool shared
Definition: tidbitmap.h:53
TBMSharedIterator * tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:1465
TBMPrivateIterator * tbm_begin_private_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:678

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 678 of file tidbitmap.c.

679{
680 TBMPrivateIterator *iterator;
681
683
684 /*
685 * Create the TBMPrivateIterator struct, with enough trailing space to
686 * serve the needs of the TBMIterateResult sub-struct.
687 */
688 iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator));
689 iterator->tbm = tbm;
690
691 /*
692 * Initialize iteration pointers.
693 */
694 iterator->spageptr = 0;
695 iterator->schunkptr = 0;
696 iterator->schunkbit = 0;
697
698 /*
699 * If we have a hashtable, create and fill the sorted page lists, unless
700 * we already did that for a previous iterator. Note that the lists are
701 * attached to the bitmap not the iterator, so they can be used by more
702 * than one iterator.
703 */
704 if (tbm->status == TBM_HASH && tbm->iterating == TBM_NOT_ITERATING)
705 {
706 pagetable_iterator i;
707 PagetableEntry *page;
708 int npages;
709 int nchunks;
710
711 if (!tbm->spages && tbm->npages > 0)
712 tbm->spages = (PagetableEntry **)
714 tbm->npages * sizeof(PagetableEntry *));
715 if (!tbm->schunks && tbm->nchunks > 0)
716 tbm->schunks = (PagetableEntry **)
718 tbm->nchunks * sizeof(PagetableEntry *));
719
720 npages = nchunks = 0;
721 pagetable_start_iterate(tbm->pagetable, &i);
722 while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
723 {
724 if (page->ischunk)
725 tbm->schunks[nchunks++] = page;
726 else
727 tbm->spages[npages++] = page;
728 }
729 Assert(npages == tbm->npages);
730 Assert(nchunks == tbm->nchunks);
731 if (npages > 1)
732 qsort(tbm->spages, npages, sizeof(PagetableEntry *),
734 if (nchunks > 1)
735 qsort(tbm->schunks, nchunks, sizeof(PagetableEntry *),
737 }
738
740
741 return iterator;
742}
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1256
void * palloc(Size size)
Definition: mcxt.c:1939
#define qsort(a, b, c, d)
Definition: port.h:479
TIDBitmap * tbm
Definition: tidbitmap.c:171
struct pagetable_hash * pagetable
Definition: tidbitmap.c:145
PagetableEntry ** schunks
Definition: tidbitmap.c:155
MemoryContext mcxt
Definition: tidbitmap.c:143
int npages
Definition: tidbitmap.c:148
int nchunks
Definition: tidbitmap.c:149
TBMStatus status
Definition: tidbitmap.c:144
PagetableEntry ** spages
Definition: tidbitmap.c:154
@ TBM_ITERATING_SHARED
Definition: tidbitmap.c:134
@ TBM_ITERATING_PRIVATE
Definition: tidbitmap.c:133
@ TBM_HASH
Definition: tidbitmap.c:124
static int tbm_comparator(const void *left, const void *right)
Definition: tidbitmap.c:1428

References Assert(), i, PagetableEntry::ischunk, TIDBitmap::iterating, 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 1545 of file tidbitmap.c.

1546{
1547 Size nbuckets;
1548
1549 /*
1550 * Estimate number of hashtable entries we can have within maxbytes. This
1551 * estimates the hash cost as sizeof(PagetableEntry), which is good enough
1552 * for our purpose. Also count an extra Pointer per entry for the arrays
1553 * created during iteration readout.
1554 */
1555 nbuckets = maxbytes /
1556 (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer));
1557 nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */
1558 nbuckets = Max(nbuckets, 16); /* sanity limit */
1559
1560 return (int) nbuckets;
1561}
#define Min(x, y)
Definition: c.h:975
#define Max(x, y)
Definition: c.h:969
char * Pointer
Definition: c.h:493
size_t Size
Definition: c.h:576
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 255 of file tidbitmap.c.

256{
257 TIDBitmap *tbm;
258
259 /* Create the TIDBitmap struct and zero all its fields */
260 tbm = makeNode(TIDBitmap);
261
263 tbm->status = TBM_EMPTY;
264
265 tbm->maxentries = tbm_calculate_entries(maxbytes);
266 tbm->lossify_start = 0;
267 tbm->dsa = dsa;
272
273 return tbm;
274}
#define InvalidDsaPointer
Definition: dsa.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
#define makeNode(_type_)
Definition: nodes.h:161
dsa_pointer ptpages
Definition: tidbitmap.c:158
dsa_pointer dsapagetableold
Definition: tidbitmap.c:157
uint32 lossify_start
Definition: tidbitmap.c:151
dsa_pointer ptchunks
Definition: tidbitmap.c:159
dsa_area * dsa
Definition: tidbitmap.c:160
dsa_pointer dsapagetable
Definition: tidbitmap.c:156
@ TBM_EMPTY
Definition: tidbitmap.c:122
int tbm_calculate_entries(Size maxbytes)
Definition: tidbitmap.c:1545

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 1597 of file tidbitmap.c.

1598{
1599 Assert(iterator && !tbm_exhausted(iterator));
1600
1601 if (iterator->shared)
1603 else
1605
1606 *iterator = (TBMIterator)
1607 {
1608 0
1609 };
1610}
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1162
void tbm_end_private_iterate(TBMPrivateIterator *iterator)
Definition: tidbitmap.c:1150
struct TBMIterator TBMIterator
static bool tbm_exhausted(TBMIterator *iterator)
Definition: tidbitmap.h:119

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 ExecEndBitmapHeapScan(), and ExecReScanBitmapHeapScan().

◆ tbm_end_private_iterate()

void tbm_end_private_iterate ( TBMPrivateIterator iterator)

Definition at line 1150 of file tidbitmap.c.

1151{
1152 pfree(iterator);
1153}
void pfree(void *pointer)
Definition: mcxt.c:2146

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 1162 of file tidbitmap.c.

1163{
1164 pfree(iterator);
1165}

References pfree().

Referenced by tbm_end_iterate().

◆ tbm_exhausted()

static bool tbm_exhausted ( TBMIterator iterator)
inlinestatic

Definition at line 119 of file tidbitmap.h.

120{
121 /*
122 * It doesn't matter if we check the private or shared iterator here. If
123 * tbm_end_iterate() was called, they will be NULL
124 */
125 return !iterator->i.private_iterator;
126}

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

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

◆ tbm_extract_page_tuple()

int tbm_extract_page_tuple ( TBMIterateResult iteritem,
OffsetNumber offsets,
uint32  max_offsets 
)

Definition at line 901 of file tidbitmap.c.

904{
905 PagetableEntry *page = iteritem->internal_page;
906 int wordnum;
907 int ntuples = 0;
908
909 for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++)
910 {
911 bitmapword w = page->words[wordnum];
912
913 if (w != 0)
914 {
915 int off = wordnum * BITS_PER_BITMAPWORD + 1;
916
917 while (w != 0)
918 {
919 if (w & 1)
920 {
921 if (ntuples < max_offsets)
922 offsets[ntuples] = (OffsetNumber) off;
923 ntuples++;
924 }
925 off++;
926 w >>= 1;
927 }
928 }
929 }
930
931 return ntuples;
932}
#define BITS_PER_BITMAPWORD
Definition: bitmapset.h:43
void * internal_page
Definition: tidbitmap.h:79
#define WORDS_PER_PAGE
Definition: tidbitmap.c:73

References BITS_PER_BITMAPWORD, TBMIterateResult::internal_page, PagetableEntry::words, and WORDS_PER_PAGE.

Referenced by BitmapHeapScanNextBlock(), and entryGetItem().

◆ tbm_free()

void tbm_free ( TIDBitmap tbm)

Definition at line 311 of file tidbitmap.c.

312{
313 if (tbm->pagetable)
314 pagetable_destroy(tbm->pagetable);
315 if (tbm->spages)
316 pfree(tbm->spages);
317 if (tbm->schunks)
318 pfree(tbm->schunks);
319 pfree(tbm);
320}

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 330 of file tidbitmap.c.

331{
332 TBMSharedIteratorState *istate = dsa_get_address(dsa, dp);
333 PTEntryArray *ptbase;
334 PTIterationArray *ptpages;
335 PTIterationArray *ptchunks;
336
337 if (DsaPointerIsValid(istate->pagetable))
338 {
339 ptbase = dsa_get_address(dsa, istate->pagetable);
340 if (pg_atomic_sub_fetch_u32(&ptbase->refcount, 1) == 0)
341 dsa_free(dsa, istate->pagetable);
342 }
343 if (DsaPointerIsValid(istate->spages))
344 {
345 ptpages = dsa_get_address(dsa, istate->spages);
346 if (pg_atomic_sub_fetch_u32(&ptpages->refcount, 1) == 0)
347 dsa_free(dsa, istate->spages);
348 }
349 if (DsaPointerIsValid(istate->schunks))
350 {
351 ptchunks = dsa_get_address(dsa, istate->schunks);
352 if (pg_atomic_sub_fetch_u32(&ptchunks->refcount, 1) == 0)
353 dsa_free(dsa, istate->schunks);
354 }
355
356 dsa_free(dsa, dp);
357}
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:105
pg_atomic_uint32 refcount
Definition: tidbitmap.c:201

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 529 of file tidbitmap.c.

530{
531 Assert(!a->iterating);
532 /* Nothing to do if a is empty */
533 if (a->nentries == 0)
534 return;
535 /* Scan through chunks and pages in a, try to match to b */
536 if (a->status == TBM_ONE_PAGE)
537 {
538 if (tbm_intersect_page(a, &a->entry1, b))
539 {
540 /* Page is now empty, remove it from a */
541 Assert(!a->entry1.ischunk);
542 a->npages--;
543 a->nentries--;
544 Assert(a->nentries == 0);
545 a->status = TBM_EMPTY;
546 }
547 }
548 else
549 {
550 pagetable_iterator i;
551 PagetableEntry *apage;
552
553 Assert(a->status == TBM_HASH);
554 pagetable_start_iterate(a->pagetable, &i);
555 while ((apage = pagetable_iterate(a->pagetable, &i)) != NULL)
556 {
557 if (tbm_intersect_page(a, apage, b))
558 {
559 /* Page or chunk is now empty, remove it from a */
560 if (apage->ischunk)
561 a->nchunks--;
562 else
563 a->npages--;
564 a->nentries--;
565 if (!pagetable_delete(a->pagetable, apage->blockno))
566 elog(ERROR, "hash table corrupted");
567 }
568 }
569 }
570}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
BlockNumber blockno
Definition: tidbitmap.c:93
@ TBM_ONE_PAGE
Definition: tidbitmap.c:123
static bool tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b)
Definition: tidbitmap.c:578

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 659 of file tidbitmap.c.

660{
661 return (tbm->nentries == 0);
662}

References TIDBitmap::nentries.

Referenced by MultiExecBitmapAnd(), and startScanEntry().

◆ tbm_iterate()

bool tbm_iterate ( TBMIterator iterator,
TBMIterateResult tbmres 
)

Definition at line 1617 of file tidbitmap.c.

1618{
1619 Assert(iterator);
1620 Assert(tbmres);
1621
1622 if (iterator->shared)
1623 return tbm_shared_iterate(iterator->i.shared_iterator, tbmres);
1624 else
1625 return tbm_private_iterate(iterator->i.private_iterator, tbmres);
1626}
bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres)
Definition: tidbitmap.c:1057
bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres)
Definition: tidbitmap.c:977

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

Referenced by bitmapheap_stream_read_next().

◆ tbm_prepare_shared_iterate()

dsa_pointer tbm_prepare_shared_iterate ( TIDBitmap tbm)

Definition at line 754 of file tidbitmap.c.

755{
756 dsa_pointer dp;
758 PTEntryArray *ptbase = NULL;
759 PTIterationArray *ptpages = NULL;
760 PTIterationArray *ptchunks = NULL;
761
762 Assert(tbm->dsa != NULL);
764
765 /*
766 * Allocate TBMSharedIteratorState from DSA to hold the shared members and
767 * lock, this will also be used by multiple worker for shared iterate.
768 */
769 dp = dsa_allocate0(tbm->dsa, sizeof(TBMSharedIteratorState));
770 istate = dsa_get_address(tbm->dsa, dp);
771
772 /*
773 * If we're not already iterating, create and fill the sorted page lists.
774 * (If we are, the sorted page lists are already stored in the TIDBitmap,
775 * and we can just reuse them.)
776 */
777 if (tbm->iterating == TBM_NOT_ITERATING)
778 {
779 pagetable_iterator i;
780 PagetableEntry *page;
781 int idx;
782 int npages;
783 int nchunks;
784
785 /*
786 * Allocate the page and chunk array memory from the DSA to share
787 * across multiple processes.
788 */
789 if (tbm->npages)
790 {
791 tbm->ptpages = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
792 tbm->npages * sizeof(int));
793 ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
794 pg_atomic_init_u32(&ptpages->refcount, 0);
795 }
796 if (tbm->nchunks)
797 {
798 tbm->ptchunks = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) +
799 tbm->nchunks * sizeof(int));
800 ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
801 pg_atomic_init_u32(&ptchunks->refcount, 0);
802 }
803
804 /*
805 * If TBM status is TBM_HASH then iterate over the pagetable and
806 * convert it to page and chunk arrays. But if it's in the
807 * TBM_ONE_PAGE mode then directly allocate the space for one entry
808 * from the DSA.
809 */
810 npages = nchunks = 0;
811 if (tbm->status == TBM_HASH)
812 {
813 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
814
815 pagetable_start_iterate(tbm->pagetable, &i);
816 while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL)
817 {
818 idx = page - ptbase->ptentry;
819 if (page->ischunk)
820 ptchunks->index[nchunks++] = idx;
821 else
822 ptpages->index[npages++] = idx;
823 }
824
825 Assert(npages == tbm->npages);
826 Assert(nchunks == tbm->nchunks);
827 }
828 else if (tbm->status == TBM_ONE_PAGE)
829 {
830 /*
831 * In one page mode allocate the space for one pagetable entry,
832 * initialize it, and directly store its index (i.e. 0) in the
833 * page array.
834 */
835 tbm->dsapagetable = dsa_allocate(tbm->dsa, sizeof(PTEntryArray) +
836 sizeof(PagetableEntry));
837 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
838 memcpy(ptbase->ptentry, &tbm->entry1, sizeof(PagetableEntry));
839 ptpages->index[0] = 0;
840 }
841
842 if (ptbase != NULL)
843 pg_atomic_init_u32(&ptbase->refcount, 0);
844 if (npages > 1)
845 qsort_arg(ptpages->index, npages, sizeof(int),
847 if (nchunks > 1)
848 qsort_arg(ptchunks->index, nchunks, sizeof(int),
850 }
851
852 /*
853 * Store the TBM members in the shared state so that we can share them
854 * across multiple processes.
855 */
856 istate->nentries = tbm->nentries;
857 istate->maxentries = tbm->maxentries;
858 istate->npages = tbm->npages;
859 istate->nchunks = tbm->nchunks;
860 istate->pagetable = tbm->dsapagetable;
861 istate->spages = tbm->ptpages;
862 istate->schunks = tbm->ptchunks;
863
864 ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable);
865 ptpages = dsa_get_address(tbm->dsa, tbm->ptpages);
866 ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
867
868 /*
869 * For every shared iterator referring to pagetable and iterator array,
870 * increase the refcount by 1 so that while freeing the shared iterator we
871 * don't free pagetable and iterator array until its refcount becomes 0.
872 */
873 if (ptbase != NULL)
875 if (ptpages != NULL)
876 pg_atomic_add_fetch_u32(&ptpages->refcount, 1);
877 if (ptchunks != NULL)
878 pg_atomic_add_fetch_u32(&ptchunks->refcount, 1);
879
880 /* Initialize the iterator lock */
882
883 /* Initialize the shared iterator state */
884 istate->schunkbit = 0;
885 istate->schunkptr = 0;
886 istate->spageptr = 0;
887
889
890 return dp;
891}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
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:721
@ LWTRANCHE_SHARED_TIDBITMAP
Definition: lwlock.h:205
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:106
int index[FLEXIBLE_ARRAY_MEMBER]
Definition: tidbitmap.c:202
PagetableEntry entry1
Definition: tidbitmap.c:152
static int tbm_shared_comparator(const void *left, const void *right, void *arg)
Definition: tidbitmap.c:1442

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()

bool tbm_private_iterate ( TBMPrivateIterator iterator,
TBMIterateResult tbmres 
)

Definition at line 977 of file tidbitmap.c.

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

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

Referenced by entryGetItem(), and tbm_iterate().

◆ tbm_shared_iterate()

bool tbm_shared_iterate ( TBMSharedIterator iterator,
TBMIterateResult tbmres 
)

Definition at line 1057 of file tidbitmap.c.

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

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

Referenced by tbm_iterate().

◆ tbm_union()

void tbm_union ( TIDBitmap a,
const TIDBitmap b 
)

Definition at line 447 of file tidbitmap.c.

448{
449 Assert(!a->iterating);
450 /* Nothing to do if b is empty */
451 if (b->nentries == 0)
452 return;
453 /* Scan through chunks and pages in b, merge into a */
454 if (b->status == TBM_ONE_PAGE)
455 tbm_union_page(a, &b->entry1);
456 else
457 {
458 pagetable_iterator i;
459 PagetableEntry *bpage;
460
461 Assert(b->status == TBM_HASH);
462 pagetable_start_iterate(b->pagetable, &i);
463 while ((bpage = pagetable_iterate(b->pagetable, &i)) != NULL)
464 tbm_union_page(a, bpage);
465 }
466}
static void tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage)
Definition: tidbitmap.c:470

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

Referenced by MultiExecBitmapOr().