aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/nbtree/nbtree.c4
-rw-r--r--src/backend/access/nbtree/nbtsearch.c40
2 files changed, 17 insertions, 27 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 484ede8c2e1..2919b12639d 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -762,13 +762,15 @@ _bt_parallel_done(IndexScanDesc scan)
BTParallelScanDesc btscan;
bool status_changed = false;
+ Assert(!BTScanPosIsValid(so->currPos));
+
/* Do nothing, for non-parallel scans */
if (parallel_scan == NULL)
return;
/*
* Should not mark parallel scan done when there's still a pending
- * primitive index scan
+ * primitive index scan (defensive)
*/
if (so->needPrimScan)
return;
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index e718668ed69..177bc226aaf 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -1161,28 +1161,18 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* If we found no usable boundary keys, we have to start from one end of
* the tree. Walk down that edge to the first or last key, and scan from
* there.
+ *
+ * Note: calls _bt_readfirstpage for us, which releases the parallel scan.
*/
if (keysz == 0)
- {
- bool match;
-
- match = _bt_endpoint(scan, dir);
-
- if (!match)
- {
- /* No match, so mark (parallel) scan finished */
- _bt_parallel_done(scan);
- }
-
- return match;
- }
+ return _bt_endpoint(scan, dir);
/*
* We want to start the scan somewhere within the index. Set up an
* insertion scankey we can use to search for the boundary point we
* identified above. The insertion scankey is built using the keys
* identified by startKeys[]. (Remaining insertion scankey fields are
- * initialized after initial-positioning strategy is finalized.)
+ * initialized after initial-positioning scan keys are finalized.)
*/
Assert(keysz <= INDEX_MAX_KEYS);
for (i = 0; i < keysz; i++)
@@ -1425,12 +1415,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
if (!BufferIsValid(so->currPos.buf))
{
- /*
- * Mark parallel scan as done, so that all the workers can finish
- * their scan.
- */
_bt_parallel_done(scan);
- BTScanPosInvalidate(so->currPos);
return false;
}
}
@@ -2267,8 +2252,8 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno,
!so->currPos.moreRight : !so->currPos.moreLeft))
{
/* most recent _bt_readpage call (for lastcurrblkno) ended scan */
- _bt_parallel_done(scan);
BTScanPosInvalidate(so->currPos);
+ _bt_parallel_done(scan);
return false;
}
@@ -2288,8 +2273,8 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno,
if (so->currPos.buf == InvalidBuffer)
{
/* must have been a concurrent deletion of leftmost page */
- _bt_parallel_done(scan);
BTScanPosInvalidate(so->currPos);
+ _bt_parallel_done(scan);
return false;
}
}
@@ -2564,8 +2549,10 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
*
* This is used by _bt_first() to set up a scan when we've determined
* that the scan must start at the beginning or end of the index (for
- * a forward or backward scan respectively). Exit conditions are the
- * same as for _bt_first().
+ * a forward or backward scan respectively).
+ *
+ * Parallel scan callers must have seized the scan before calling here.
+ * Exit conditions are the same as for _bt_first().
*/
static bool
_bt_endpoint(IndexScanDesc scan, ScanDirection dir)
@@ -2577,10 +2564,11 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
OffsetNumber start;
BTScanPosItem *currItem;
+ Assert(!BTScanPosIsValid(so->currPos));
+
/*
* Scan down to the leftmost or rightmost leaf page. This is a simplified
- * version of _bt_search(). We don't maintain a stack since we know we
- * won't need it.
+ * version of _bt_search().
*/
so->currPos.buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir));
@@ -2591,7 +2579,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
* exists.
*/
PredicateLockRelation(rel, scan->xs_snapshot);
- BTScanPosInvalidate(so->currPos);
+ _bt_parallel_done(scan);
return false;
}