diff options
Diffstat (limited to 'src/backend/access/nbtree/nbtree.c')
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 2919b12639d..dd76fe1da90 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -596,9 +596,7 @@ btparallelrescan(IndexScanDesc scan) * scan, and *last_curr_page returns the page that *next_scan_page came from. * An invalid *next_scan_page means the scan hasn't yet started, or that * caller needs to start the next primitive index scan (if it's the latter - * case we'll set so.needPrimScan). The first time a participating process - * reaches the last page, it will return true and set *next_scan_page to - * P_NONE; after that, further attempts to seize the scan will return false. + * case we'll set so.needPrimScan). * * Callers should ignore the value of *next_scan_page and *last_curr_page if * the return value is false. @@ -608,12 +606,13 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, BlockNumber *last_curr_page, bool first) { BTScanOpaque so = (BTScanOpaque) scan->opaque; - bool exit_loop = false; - bool status = true; + bool exit_loop = false, + status = true, + endscan = false; ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; - *next_scan_page = P_NONE; + *next_scan_page = InvalidBlockNumber; *last_curr_page = InvalidBlockNumber; /* @@ -657,6 +656,13 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, /* We're done with this parallel index scan */ status = false; } + else if (btscan->btps_pageStatus == BTPARALLEL_IDLE && + btscan->btps_nextScanPage == P_NONE) + { + /* End this parallel index scan */ + status = false; + endscan = true; + } else if (btscan->btps_pageStatus == BTPARALLEL_NEED_PRIMSCAN) { Assert(so->numArrayKeys); @@ -673,7 +679,6 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, array->cur_elem = btscan->btps_arrElems[i]; skey->sk_argument = array->elem_values[array->cur_elem]; } - *next_scan_page = InvalidBlockNumber; exit_loop = true; } else @@ -701,6 +706,7 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, * of advancing it to a new page! */ btscan->btps_pageStatus = BTPARALLEL_ADVANCING; + Assert(btscan->btps_nextScanPage != P_NONE); *next_scan_page = btscan->btps_nextScanPage; *last_curr_page = btscan->btps_lastCurrPage; exit_loop = true; @@ -712,6 +718,10 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, } ConditionVariableCancelSleep(); + /* When the scan has reached the rightmost (or leftmost) page, end it */ + if (endscan) + _bt_parallel_done(scan); + return status; } @@ -724,6 +734,10 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, * that it can be passed to _bt_parallel_primscan_schedule, should caller * determine that another primitive index scan is required. * + * If caller's next_scan_page is P_NONE, the scan has reached the index's + * rightmost/leftmost page. This is treated as reaching the end of the scan + * within _bt_parallel_seize. + * * Note: unlike the serial case, parallel scans don't need to remember both * sibling links. next_scan_page is whichever link is next given the scan's * direction. That's all we'll ever need, since the direction of a parallel @@ -736,6 +750,8 @@ _bt_parallel_release(IndexScanDesc scan, BlockNumber next_scan_page, ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; + Assert(BlockNumberIsValid(next_scan_page)); + btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, parallel_scan->ps_offset); @@ -770,7 +786,7 @@ _bt_parallel_done(IndexScanDesc scan) /* * Should not mark parallel scan done when there's still a pending - * primitive index scan (defensive) + * primitive index scan */ if (so->needPrimScan) return; |