Add common interface for TBMIterators
authorMelanie Plageman <[email protected]>
Wed, 18 Dec 2024 23:19:28 +0000 (18:19 -0500)
committerMelanie Plageman <[email protected]>
Wed, 18 Dec 2024 23:19:28 +0000 (18:19 -0500)
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

src/backend/access/gin/ginget.c
src/backend/access/gin/ginscan.c
src/backend/access/heap/heapam_handler.c
src/backend/executor/nodeBitmapHeapscan.c
src/backend/nodes/tidbitmap.c
src/include/access/gin_private.h
src/include/access/relscan.h
src/include/nodes/execnodes.h
src/include/nodes/tidbitmap.h
src/tools/pgindent/typedefs.list

index 0b4f2ebadb6c85216786f1c55acf198faa1d020a..e8e0eab655213c47c2e490ea176d266bd4b5e33a 100644 (file)
@@ -373,7 +373,7 @@ restartScanEntry:
            if (entry->matchBitmap)
            {
                if (entry->matchIterator)
-                   tbm_end_iterate(entry->matchIterator);
+                   tbm_end_private_iterate(entry->matchIterator);
                entry->matchIterator = NULL;
                tbm_free(entry->matchBitmap);
                entry->matchBitmap = NULL;
@@ -385,7 +385,8 @@ restartScanEntry:
 
        if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap))
        {
-           entry->matchIterator = tbm_begin_iterate(entry->matchBitmap);
+           entry->matchIterator =
+               tbm_begin_private_iterate(entry->matchBitmap);
            entry->isFinished = false;
        }
    }
@@ -832,12 +833,13 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
                   (ItemPointerIsLossyPage(&advancePast) &&
                    entry->matchResult->blockno == advancePastBlk))
            {
-               entry->matchResult = tbm_iterate(entry->matchIterator);
+               entry->matchResult =
+                   tbm_private_iterate(entry->matchIterator);
 
                if (entry->matchResult == NULL)
                {
                    ItemPointerSetInvalid(&entry->curItem);
-                   tbm_end_iterate(entry->matchIterator);
+                   tbm_end_private_iterate(entry->matchIterator);
                    entry->matchIterator = NULL;
                    entry->isFinished = true;
                    break;
index f2fd62afbbfd91c8d512d58ccc1172f7088ad9e4..2c6631c914d974fbd2b4f8011e3a14ab39769c43 100644 (file)
@@ -246,7 +246,7 @@ ginFreeScanKeys(GinScanOpaque so)
        if (entry->list)
            pfree(entry->list);
        if (entry->matchIterator)
-           tbm_end_iterate(entry->matchIterator);
+           tbm_end_private_iterate(entry->matchIterator);
        if (entry->matchBitmap)
            tbm_free(entry->matchBitmap);
    }
index 689773ff2397a615597bc5c2b95877d64ecc0378..adf968df42bae93e6d89985c8d7ddcf13c52b79c 100644 (file)
@@ -2138,7 +2138,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan,
        if (scan->st.bitmap.rs_shared_iterator)
            tbmres = tbm_shared_iterate(scan->st.bitmap.rs_shared_iterator);
        else
-           tbmres = tbm_iterate(scan->st.bitmap.rs_iterator);
+           tbmres = tbm_private_iterate(scan->st.bitmap.rs_iterator);
 
        if (tbmres == NULL)
            return false;
index 689bde16dd2c17e1f7c38ff924243f3b01c50455..d9e7a516a078cd8a1f257fca8f2cffef10f95422 100644 (file)
@@ -95,7 +95,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
     */
    if (!node->initialized)
    {
-       TBMIterator *tbmiterator = NULL;
+       TBMPrivateIterator *tbmiterator = NULL;
        TBMSharedIterator *shared_tbmiterator = NULL;
 
        if (!pstate)
@@ -106,12 +106,12 @@ BitmapHeapNext(BitmapHeapScanState *node)
                elog(ERROR, "unrecognized result from subplan");
 
            node->tbm = tbm;
-           tbmiterator = tbm_begin_iterate(tbm);
+           tbmiterator = tbm_begin_private_iterate(tbm);
 
 #ifdef USE_PREFETCH
            if (node->prefetch_maximum > 0)
            {
-               node->prefetch_iterator = tbm_begin_iterate(tbm);
+               node->prefetch_iterator = tbm_begin_private_iterate(tbm);
                node->prefetch_pages = 0;
                node->prefetch_target = -1;
            }
@@ -332,7 +332,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
 
    if (pstate == NULL)
    {
-       TBMIterator *prefetch_iterator = node->prefetch_iterator;
+       TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
        if (node->prefetch_pages > 0)
        {
@@ -341,7 +341,7 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node)
        }
        else if (prefetch_iterator)
        {
-           tbmpre = tbm_iterate(prefetch_iterator);
+           tbmpre = tbm_private_iterate(prefetch_iterator);
            node->prefetch_blockno = tbmpre ? tbmpre->blockno :
                InvalidBlockNumber;
        }
@@ -446,19 +446,20 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
 
    if (pstate == NULL)
    {
-       TBMIterator *prefetch_iterator = node->prefetch_iterator;
+       TBMPrivateIterator *prefetch_iterator = node->prefetch_iterator;
 
        if (prefetch_iterator)
        {
            while (node->prefetch_pages < node->prefetch_target)
            {
-               TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
+               TBMIterateResult *tbmpre;
                bool        skip_fetch;
 
+               tbmpre = tbm_private_iterate(prefetch_iterator);
                if (tbmpre == NULL)
                {
                    /* No more pages to prefetch */
-                   tbm_end_iterate(prefetch_iterator);
+                   tbm_end_private_iterate(prefetch_iterator);
                    node->prefetch_iterator = NULL;
                    break;
                }
@@ -594,7 +595,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
        if (scan->st.bitmap.rs_iterator)
        {
-           tbm_end_iterate(scan->st.bitmap.rs_iterator);
+           tbm_end_private_iterate(scan->st.bitmap.rs_iterator);
            scan->st.bitmap.rs_iterator = NULL;
        }
 
@@ -604,7 +605,7 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
 
    /* release bitmaps and buffers if any */
    if (node->prefetch_iterator)
-       tbm_end_iterate(node->prefetch_iterator);
+       tbm_end_private_iterate(node->prefetch_iterator);
    if (node->shared_prefetch_iterator)
        tbm_end_shared_iterate(node->shared_prefetch_iterator);
    if (node->tbm)
@@ -685,7 +686,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
 
        if (scanDesc->st.bitmap.rs_iterator)
        {
-           tbm_end_iterate(scanDesc->st.bitmap.rs_iterator);
+           tbm_end_private_iterate(scanDesc->st.bitmap.rs_iterator);
            scanDesc->st.bitmap.rs_iterator = NULL;
        }
 
@@ -699,7 +700,7 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
     * release bitmaps and buffers if any
     */
    if (node->prefetch_iterator)
-       tbm_end_iterate(node->prefetch_iterator);
+       tbm_end_private_iterate(node->prefetch_iterator);
    if (node->tbm)
        tbm_free(node->tbm);
    if (node->shared_prefetch_iterator)
index e8ab5d78fcc7ceaa2d3f4a32681fdcb74ec7d47c..687d6f1763632820a136a0f151324bb7aea5b426 100644 (file)
@@ -170,12 +170,12 @@ struct TIDBitmap
 };
 
 /*
- * When iterating over a bitmap in sorted order, a TBMIterator is used to
- * track our progress.  There can be several iterators scanning the same
- * bitmap concurrently.  Note that the bitmap becomes read-only as soon as
- * any iterator is created.
+ * When iterating over a backend-local bitmap in sorted order, a
+ * TBMPrivateIterator is used to track our progress.  There can be several
+ * iterators scanning the same bitmap concurrently.  Note that the bitmap
+ * becomes read-only as soon as any iterator is created.
  */
-struct TBMIterator
+struct TBMPrivateIterator
 {
    TIDBitmap  *tbm;            /* TIDBitmap we're iterating over */
    int         spageptr;       /* next spages index */
@@ -213,8 +213,8 @@ typedef struct PTIterationArray
 } PTIterationArray;
 
 /*
- * same as TBMIterator, but it is used for joint iteration, therefore this
- * also holds a reference to the shared state.
+ * same as TBMPrivateIterator, but it is used for joint iteration, therefore
+ * this also holds a reference to the shared state.
  */
 struct TBMSharedIterator
 {
@@ -673,31 +673,32 @@ tbm_is_empty(const TIDBitmap *tbm)
 }
 
 /*
- * tbm_begin_iterate - prepare to iterate through a TIDBitmap
+ * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap
  *
- * The TBMIterator struct is created in the caller's memory context.
- * For a clean shutdown of the iteration, call tbm_end_iterate; but it's
- * okay to just allow the memory context to be released, too.  It is caller's
- * responsibility not to touch the TBMIterator anymore once the TIDBitmap
- * is freed.
+ * The TBMPrivateIterator struct is created in the caller's memory context.
+ * For a clean shutdown of the iteration, call tbm_end_private_iterate; but
+ * it's okay to just allow the memory context to be released, too.  It is
+ * caller's responsibility not to touch the TBMPrivateIterator anymore once
+ * the TIDBitmap is freed.
  *
  * NB: after this is called, it is no longer allowed to modify the contents
  * of the bitmap.  However, you can call this multiple times to scan the
  * contents repeatedly, including parallel scans.
  */
-TBMIterator *
-tbm_begin_iterate(TIDBitmap *tbm)
+TBMPrivateIterator *
+tbm_begin_private_iterate(TIDBitmap *tbm)
 {
-   TBMIterator *iterator;
+   TBMPrivateIterator *iterator;
 
    Assert(tbm->iterating != TBM_ITERATING_SHARED);
 
    /*
-    * Create the TBMIterator struct, with enough trailing space to serve the
-    * needs of the TBMIterateResult sub-struct.
+    * Create the TBMPrivateIterator struct, with enough trailing space to
+    * serve the needs of the TBMIterateResult sub-struct.
     */
-   iterator = (TBMIterator *) palloc(sizeof(TBMIterator) +
-                                     MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber));
+   iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator) +
+                                            MAX_TUPLES_PER_PAGE *
+                                            sizeof(OffsetNumber));
    iterator->tbm = tbm;
 
    /*
@@ -878,7 +879,7 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm)
    ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks);
 
    /*
-    * For every shared iterator, referring to pagetable and iterator array,
+    * For every shared iterator referring to pagetable and iterator array,
     * increase the refcount by 1 so that while freeing the shared iterator we
     * don't free pagetable and iterator array until its refcount becomes 0.
     */
@@ -956,7 +957,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 }
 
 /*
- * tbm_iterate - scan through next page of a TIDBitmap
+ * 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
@@ -968,7 +969,7 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
  * testing, recheck is always set true when ntuples < 0.)
  */
 TBMIterateResult *
-tbm_iterate(TBMIterator *iterator)
+tbm_private_iterate(TBMPrivateIterator *iterator)
 {
    TIDBitmap  *tbm = iterator->tbm;
    TBMIterateResult *output = &(iterator->output);
@@ -1136,14 +1137,14 @@ tbm_shared_iterate(TBMSharedIterator *iterator)
 }
 
 /*
- * tbm_end_iterate - finish an iteration over a TIDBitmap
+ * tbm_end_private_iterate - finish an iteration over a TIDBitmap
  *
  * Currently this is just a pfree, but it might do more someday.  (For
  * instance, it could be useful to count open iterators and allow the
  * bitmap to return to read/write status when there are no more iterators.)
  */
 void
-tbm_end_iterate(TBMIterator *iterator)
+tbm_end_private_iterate(TBMPrivateIterator *iterator)
 {
    pfree(iterator);
 }
@@ -1556,3 +1557,66 @@ tbm_calculate_entries(double maxbytes)
 
    return nbuckets;
 }
+
+/*
+ * Create a shared or private bitmap iterator and start iteration.
+ *
+ * `tbm` is only used to create the private iterator and dsa and dsp are only
+ * used to create the shared iterator.
+ *
+ * Before invoking tbm_begin_iterate() to create a shared iterator, one
+ * process must already have invoked tbm_prepare_shared_iterate() to create
+ * and set up the TBMSharedIteratorState.
+ */
+TBMIterator
+tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
+{
+   TBMIterator iterator = {0};
+
+   /* Allocate a private iterator and attach the shared state to it */
+   if (DsaPointerIsValid(dsp))
+   {
+       iterator.shared = true;
+       iterator.i.shared_iterator = tbm_attach_shared_iterate(dsa, dsp);
+   }
+   else
+   {
+       iterator.shared = false;
+       iterator.i.private_iterator = tbm_begin_private_iterate(tbm);
+   }
+
+   return iterator;
+}
+
+/*
+ * Clean up shared or private bitmap iterator.
+ */
+void
+tbm_end_iterate(TBMIterator *iterator)
+{
+   Assert(iterator);
+
+   if (iterator->shared)
+       tbm_end_shared_iterate(iterator->i.shared_iterator);
+   else
+       tbm_end_private_iterate(iterator->i.private_iterator);
+
+   *iterator = (TBMIterator)
+   {
+       0
+   };
+}
+
+/*
+ * Get the next TBMIterateResult from the shared or private bitmap iterator.
+ */
+TBMIterateResult *
+tbm_iterate(TBMIterator *iterator)
+{
+   Assert(iterator);
+
+   if (iterator->shared)
+       return tbm_shared_iterate(iterator->i.shared_iterator);
+   else
+       return tbm_private_iterate(iterator->i.private_iterator);
+}
index 3013a44bae1c2c506153876e11ec202bfc7a5a15..788005093677535bd8222752fe1243efead63916 100644 (file)
@@ -352,7 +352,7 @@ typedef struct GinScanEntryData
 
    /* for a partial-match or full-scan query, we accumulate all TIDs here */
    TIDBitmap  *matchBitmap;
-   TBMIterator *matchIterator;
+   TBMPrivateIterator *matchIterator;
    TBMIterateResult *matchResult;
 
    /* used for Posting list and one page in Posting tree */
index e1884acf493cc4ce3041e3b2527d38d6ca87add4..153561addc0fe6e10fd135b90e85a23a0e59699d 100644 (file)
@@ -25,7 +25,7 @@
 
 struct ParallelTableScanDescData;
 
-struct TBMIterator;
+struct TBMPrivateIterator;
 struct TBMSharedIterator;
 
 /*
@@ -48,7 +48,7 @@ typedef struct TableScanDescData
        /* Iterators for Bitmap Table Scans */
        struct
        {
-           struct TBMIterator *rs_iterator;
+           struct TBMPrivateIterator *rs_iterator;
            struct TBMSharedIterator *rs_shared_iterator;
        }           bitmap;
 
index 7f71b7625df7c9656e7975162849172fc1bf9993..f0b5fa421ca9299cad2b81dc0c27c5db30cbfbd9 100644 (file)
@@ -1853,7 +1853,7 @@ typedef struct BitmapHeapScanState
    TIDBitmap  *tbm;
    Buffer      pvmbuffer;
    BitmapHeapScanInstrumentation stats;
-   TBMIterator *prefetch_iterator;
+   TBMPrivateIterator *prefetch_iterator;
    int         prefetch_pages;
    int         prefetch_target;
    int         prefetch_maximum;
index 1945f0639bf15667878ab58916667a23fc10a5b4..d746963976489c91b390cc3403cec5e2bfc6382e 100644 (file)
  */
 typedef struct TIDBitmap TIDBitmap;
 
-/* Likewise, TBMIterator is private */
-typedef struct TBMIterator TBMIterator;
+/* Likewise, TBMPrivateIterator is private */
+typedef struct TBMPrivateIterator TBMPrivateIterator;
 typedef struct TBMSharedIterator TBMSharedIterator;
 
+/*
+ * Callers with both private and shared implementations can use this unified
+ * API.
+ */
+typedef struct TBMIterator
+{
+   bool        shared;
+   union
+   {
+       TBMPrivateIterator *private_iterator;
+       TBMSharedIterator *shared_iterator;
+   }           i;
+} TBMIterator;
+
 /* Result structure for tbm_iterate */
 typedef struct TBMIterateResult
 {
@@ -62,14 +76,20 @@ extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
 extern bool tbm_is_empty(const TIDBitmap *tbm);
 
-extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm);
 extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
-extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_private_iterate(TBMPrivateIterator *iterator);
 extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
-extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_private_iterate(TBMPrivateIterator *iterator);
 extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
 extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
                                                    dsa_pointer dp);
 extern long tbm_calculate_entries(double maxbytes);
 
+extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm,
+                                    dsa_area *dsa, dsa_pointer dsp);
+extern void tbm_end_iterate(TBMIterator *iterator);
+
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+
 #endif                         /* TIDBITMAP_H */
index ce33e55bf1d3a8beb19de27fdc174a019a306daa..cda21239cbc1091687cb5ced31c42b156fed57b8 100644 (file)
@@ -2812,6 +2812,7 @@ TAR_MEMBER
 TBMIterateResult
 TBMIteratingState
 TBMIterator
+TBMPrivateIterator
 TBMSharedIterator
 TBMSharedIteratorState
 TBMStatus