8000 DEBUG: make _bt_advance_array_keys invariant violations into errors · petergeoghegan/postgres@f485cf8 · GitHub
[go: up one dir, main page]

Skip to content

Commit f485cf8

Browse files
DEBUG: make _bt_advance_array_keys invariant violations into errors
Promotes the precondition and postcondition assertions within _bt_advance_array_keys into "can't happen" elog ERRORs. Also detects repeat accesses to the same leaf page, which aren't expected (barring certain limited edge cases, which are accounted for here).
1 parent 100c2ae commit f485cf8

File tree

4 files changed

+62
-5
lines changed

4 files changed

+62
-5
lines changed

src/backend/access/nbtree/nbtree.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ btbeginscan(Relation rel, int nkeys, int norderbys)
395395
else
396396
so->keyData = NULL;
397397

398+
so->bmsPages = NULL;
398399
so->skipScan = false;
399400
so->needPrimScan = false;
400401
so->scanBehind = false;
@@ -457,6 +458,8 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
457458
_bt_killitems(scan);
458459
BTScanPosUnpinIfPinned(so->currPos);
459460
BTScanPosInvalidate(so->currPos);
461+
bms_free(so->bmsPages);
462+
so->bmsPages = NULL;
460463
if (so->log_btree_verbosity)
461464
appendStringInfo(&so->debugstr, "btrescan: BTScanPosInvalidate() called for currPos\n");
462465
}
@@ -644,6 +647,8 @@ btrestrpos(IndexScanDesc scan)
644647
{
645648
_bt_start_array_keys(scan, so->currPos.dir);
646649
so->needPrimScan = false;
650+
bms_free(so->bmsPages);
651+
so->bmsPages = NULL;
647652
}
648653
}
649654
else

src/backend/access/nbtree/nbtsearch.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
11991199

12001200
Assert(!BTScanPosIsValid(so->currPos));
12011201

1202+
CHECK_FOR_INTERRUPTS();
1203+
12021204
/*
12031205
* Examine the scan keys and eliminate any redundant keys; also mark the
12041206
* keys that must be matched to continue the scan.
@@ -2043,6 +2045,17 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
20432045

20442046
so->npages++;
20452047

2048+
if (so->arrayKeys)
2049+
{
2050+
int pageNum = (int) so->currPos.currPage;
2051+
2052+
if ((ScanDirectionIsForward(dir) || offnum >= minoff) &&
2053+
bms_is_member(pageNum, so->bmsPages))
2054+
elog(ERROR, "pageNum %d already visited\n\n%s", pageNum,
2055+
so->debugstr.data);
2056+
so->bmsPages = bms_add_member(so->bmsPages, pageNum);
2057+
}
2058+
20462059
if (ScanDirectionIsForward(dir))
20472060
{
20482061
/* SK_SEARCHARRAY forward scans must provide high key up front */
@@ -2820,8 +2833,19 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
28202833
* keys as-is, since the next _bt_readpage will advance them.)
28212834
*/
28222835
if (so->currPos.dir != dir)
2836+
{
28232837
so->needPrimScan = false;
28242838

2839+
/*
2840+
* Have to forget every block we've read so far when scan direction
2841+
* changes. Cannot just delete previously read block (that we're
2842+
* about to read once more), since there might also be blocks beyond
2843+
* that one that were read way earlier on.
2844+
*/
2845+
bms_free(so->bmsPages);
2846+
so->bmsPages = NULL;
2847+
}
2848+
28252849
return _bt_readnextpage(scan, blkno, lastcurrblkno, dir, false);
28262850
}
28272851

@@ -2968,6 +2992,8 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno,
29682992
/* most recent _bt_readpage call (for lastcurrblkno) ended scan */
29692993
Assert(so->currPos.currPage == lastcurrblkno && !seized);
29702994
BTScanPosInvalidate(so->currPos);
2995+
bms_free(so->bmsPages);
2996+
so->bmsPages = NULL;
29712997
_bt_parallel_done(scan); /* iff !so->needPrimScan */
29722998
return false;
29732999
}
@@ -2980,6 +3006,8 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno,
29803006
{
29813007
/* whole scan is now done (or another primitive scan required) */
29823008
BTScanPosInvalidate(so->currPos);
3009+
bms_free(so->bmsPages);
3010+
so->bmsPages = NULL;
29833011
return false;
29843012
}
29853013

@@ -2998,6 +3026,8 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno,
29983026
{
29993027
/* must have been a concurrent deletion of leftmost page */
30003028
BTScanPosInvalidate(so->currPos);
3029+
bms_free(so->bmsPages);
3030+
so->bmsPages = NULL;
30013031
_bt_parallel_done(scan);
30023032
return false;
30033033
}

src/backend/access/nbtree/nbtutils.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,8 +1542,19 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate,
15421542
/*
15431543
* Precondition array state assertion
15441544
*/
1545-
Assert(!_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc,
1546-
tupnatts, false, 0, NULL));
1545+
if (!(!_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc,
1546+
tupnatts, false, 0, NULL)))
1547+
{
1548+
char *pitup;
1549+
1550+
pitup = _nbtree_print_itup(tuple, rel);
1551+
1552+
elog(ERROR, "pitup: %s\n\n %s", pitup, so->debugstr.data);
1553+
1554+
if (pitup)
1555+
pfree(pitup);
1556+
1557+
}
15471558

15481559
/*
15491560
* Once we return we'll have a new set of required array keys, so
@@ -2026,9 +2037,19 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate,
20262037
* scan keys required in the opposite direction only; those aren't tracked
20272038
* by all_required_satisfied.
20282039
*/
2029-
Assert(_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, tupnatts,
2030-
false, 0, NULL) ==
2031-
!all_required_satisfied);
2040+
if (!(_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, tupnatts,
2041+
false, 0,
2042+
NULL) == !all_required_satisfied))
2043+
{
2044+
char *pitup;
2045+
2046+
pitup = _nbtree_print_itup(tuple, rel);
2047+
2048+
elog(ERROR, "later pitup: %s\n\n %s", pitup, so->debugstr.data);
2049+
2050+
if (pitup)
2051+
pfree(pitup);
2052+
}
20322053

20332054
/*
20342055
* We generally permit primitive index scans to continue onto the next

src/include/access/nbtree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ typedef struct BTScanOpaqueData
10561056
bool qual_ok; /* false if qual can never be satisfied */
10571057
int numberOfKeys; /* number of preprocessed scan keys */
10581058
ScanKey keyData; /* array of preprocessed scan keys */
1059+
Bitmapset *bmsPages;
10591060

10601061
/* workspace for SK_SEARCHARRAY support */
10611062
int numArrayKeys; /* number of equality-type array keys */

0 commit comments

Comments
 (0)
0