Skip to content

Commit d088ba5

Browse files
nbtree: Allocate new pages in separate function.
Split nbtree's _bt_getbuf function is two: code that read locks or write locks existing pages remains in _bt_getbuf, while code that deals with allocating new pages is moved to a new, dedicated function called _bt_allocbuf. This simplifies most _bt_getbuf callers, since it is no longer necessary for them to pass a heaprel argument. Many of the changes to nbtree from commit 61b313e can be reverted. This minimizes the divergence between HEAD/PostgreSQL 16 and earlier release branches. _bt_allocbuf replaces the previous nbtree idiom of passing P_NEW to _bt_getbuf. There are only 3 affected call sites, all of which continue to pass a heaprel for recovery conflict purposes. Note that nbtree's use of P_NEW was superficial; nbtree never actually relied on the P_NEW code paths in bufmgr.c, so this change is strictly mechanical. GiST already took the same approach; it has a dedicated function for allocating new pages called gistNewBuffer(). That factor allowed commit 61b313e to make much more targeted changes to GiST. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Heikki Linnakangas <hlinnaka@iki.fi> Discussion: https://postgr.es/m/CAH2-Wz=8Z9qY58bjm_7TAHgtW6RzZ5Ke62q5emdCEy9BAzwhmg@mail.gmail.com
1 parent fe879ae commit d088ba5

File tree

12 files changed

+269
-255
lines changed

12 files changed

+269
-255
lines changed

contrib/amcheck/verify_nbtree.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ static inline bool invariant_l_nontarget_offset(BtreeCheckState *state,
183183
OffsetNumber upperbound);
184184
static Page palloc_btree_page(BtreeCheckState *state, BlockNumber blocknum);
185185
static inline BTScanInsert bt_mkscankey_pivotsearch(Relation rel,
186-
Relation heaprel,
187186
IndexTuple itup);
188187
static ItemId PageGetItemIdCareful(BtreeCheckState *state, BlockNumber block,
189188
Page page, OffsetNumber offset);
@@ -332,7 +331,7 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
332331
RelationGetRelationName(indrel))));
333332

334333
/* Extract metadata from metapage, and sanitize it in passing */
335-
_bt_metaversion(indrel, heaprel, &heapkeyspace, &allequalimage);
334+
_bt_metaversion(indrel, &heapkeyspace, &allequalimage);
336335
if (allequalimage && !heapkeyspace)
337336
ereport(ERROR,
338337
(errcode(ERRCODE_INDEX_CORRUPTED),
@@ -1259,7 +1258,7 @@ bt_target_page_check(BtreeCheckState *state)
12591258
}
12601259

12611260
/* Build insertion scankey for current page offset */
1262-
skey = bt_mkscankey_pivotsearch(state->rel, state->heaprel, itup);
1261+
skey = bt_mkscankey_pivotsearch(state->rel, itup);
12631262

12641263
/*
12651264
* Make sure tuple size does not exceed the relevant BTREE_VERSION
@@ -1769,7 +1768,7 @@ bt_right_page_check_scankey(BtreeCheckState *state)
17691768
* memory remaining allocated.
17701769
*/
17711770
firstitup = (IndexTuple) PageGetItem(rightpage, rightitem);
1772-
return bt_mkscankey_pivotsearch(state->rel, state->heaprel, firstitup);
1771+
return bt_mkscankey_pivotsearch(state->rel, firstitup);
17731772
}
17741773

17751774
/*
@@ -2682,7 +2681,7 @@ bt_rootdescend(BtreeCheckState *state, IndexTuple itup)
26822681
Buffer lbuf;
26832682
bool exists;
26842683

2685-
key = _bt_mkscankey(state->rel, state->heaprel, itup);
2684+
key = _bt_mkscankey(state->rel, itup);
26862685
Assert(key->heapkeyspace && key->scantid != NULL);
26872686

26882687
/*
@@ -2695,7 +2694,7 @@ bt_rootdescend(BtreeCheckState *state, IndexTuple itup)
26952694
*/
26962695
Assert(state->readonly && state->rootdescend);
26972696
exists = false;
2698-
stack = _bt_search(state->rel, state->heaprel, key, &lbuf, BT_READ, NULL);
2697+
stack = _bt_search(state->rel, NULL, key, &lbuf, BT_READ, NULL);
26992698

27002699
if (BufferIsValid(lbuf))
27012700
{
@@ -3134,11 +3133,11 @@ palloc_btree_page(BtreeCheckState *state, BlockNumber blocknum)
31343133
* the scankey is greater.
31353134
*/
31363135
static inline BTScanInsert
3137-
bt_mkscankey_pivotsearch(Relation rel, Relation heaprel, IndexTuple itup)
3136+
bt_mkscankey_pivotsearch(Relation rel, IndexTuple itup)
31383137
{
31393138
BTScanInsert skey;
31403139

3141-
skey = _bt_mkscankey(rel, heaprel, itup);
3140+
skey = _bt_mkscankey(rel, itup);
31423141
skey->pivotsearch = true;
31433142

31443143
return skey;

src/backend/access/heap/heapam_handler.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -731,14 +731,9 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
731731
*multi_cutoff);
732732

733733

734-
/*
735-
* Set up sorting if wanted. NewHeap is being passed to
736-
* tuplesort_begin_cluster(), it could have been OldHeap too. It does not
737-
* really matter, as the goal is to have a heap relation being passed to
738-
* _bt_log_reuse_page() (which should not be called from this code path).
739-
*/
734+
/* Set up sorting if wanted */
740735
if (use_sort)
741-
tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex, NewHeap,
736+
tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex,
742737
maintenance_work_mem,
743738
NULL, TUPLESORT_NONE);
744739
else

src/backend/access/nbtree/nbtinsert.c

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static Buffer _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key,
5959
IndexTuple nposting, uint16 postingoff);
6060
static void _bt_insert_parent(Relation rel, Relation heaprel, Buffer buf,
6161
Buffer rbuf, BTStack stack, bool isroot, bool isonly);
62-
static Buffer _bt_newroot(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf);
62+
static Buffer _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf);
6363
static inline bool _bt_pgaddtup(Page page, Size itemsize, IndexTuple itup,
6464
OffsetNumber itup_off, bool newfirstdataitem);
6565
static void _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel,
@@ -110,7 +110,7 @@ _bt_doinsert(Relation rel, IndexTuple itup,
110110
bool checkingunique = (checkUnique != UNIQUE_CHECK_NO);
111111

112112
/* we need an insertion scan key to do our search, so build one */
113-
itup_key = _bt_mkscankey(rel, heapRel, itup);
113+
itup_key = _bt_mkscankey(rel, itup);
114114

115115
if (checkingunique)
116116
{
@@ -1024,13 +1024,15 @@ _bt_findinsertloc(Relation rel,
10241024
* indexes.
10251025
*/
10261026
static void
1027-
_bt_stepright(Relation rel, Relation heaprel, BTInsertState insertstate, BTStack stack)
1027+
_bt_stepright(Relation rel, Relation heaprel, BTInsertState insertstate,
1028+
BTStack stack)
10281029
{
10291030
Page page;
10301031
BTPageOpaque opaque;
10311032
Buffer rbuf;
10321033
BlockNumber rblkno;
10331034

1035+
Assert(heaprel != NULL);
10341036
page = BufferGetPage(insertstate->buf);
10351037
opaque = BTPageGetOpaque(page);
10361038

@@ -1145,7 +1147,7 @@ _bt_insertonpg(Relation rel,
11451147

11461148
/*
11471149
* Every internal page should have exactly one negative infinity item at
1148-
* all times. Only _bt_split() and _bt_newroot() should add items that
1150+
* all times. Only _bt_split() and _bt_newlevel() should add items that
11491151
* become negative infinity items through truncation, since they're the
11501152
* only routines that allocate new internal pages.
11511153
*/
@@ -1250,14 +1252,14 @@ _bt_insertonpg(Relation rel,
12501252
* only one on its tree level, but was not the root, it may have been
12511253
* the "fast root". We need to ensure that the fast root link points
12521254
* at or above the current page. We can safely acquire a lock on the
1253-
* metapage here --- see comments for _bt_newroot().
1255+
* metapage here --- see comments for _bt_newlevel().
12541256
*/
12551257
if (unlikely(split_only_page))
12561258
{
12571259
Assert(!isleaf);
12581260
Assert(BufferIsValid(cbuf));
12591261

1260-
metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
1262+
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
12611263
metapg = BufferGetPage(metabuf);
12621264
metad = BTPageGetMeta(metapg);
12631265

@@ -1421,7 +1423,7 @@ _bt_insertonpg(Relation rel,
14211423
* call _bt_getrootheight while holding a buffer lock.
14221424
*/
14231425
if (BlockNumberIsValid(blockcache) &&
1424-
_bt_getrootheight(rel, heaprel) >= BTREE_FASTPATH_MIN_LEVEL)
1426+
_bt_getrootheight(rel) >= BTREE_FASTPATH_MIN_LEVEL)
14251427
RelationSetTargetBlock(rel, blockcache);
14261428
}
14271429

@@ -1715,7 +1717,7 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf,
17151717
* way because it avoids an unnecessary PANIC when either origpage or its
17161718
* existing sibling page are corrupt.
17171719
*/
1718-
rbuf = _bt_getbuf(rel, heaprel, P_NEW, BT_WRITE);
1720+
rbuf = _bt_allocbuf(rel, heaprel);
17191721
rightpage = BufferGetPage(rbuf);
17201722
rightpagenumber = BufferGetBlockNumber(rbuf);
17211723
/* rightpage was initialized by _bt_getbuf */
@@ -1888,7 +1890,7 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf,
18881890
*/
18891891
if (!isrightmost)
18901892
{
1891-
sbuf = _bt_getbuf(rel, heaprel, oopaque->btpo_next, BT_WRITE);
1893+
sbuf = _bt_getbuf(rel, oopaque->btpo_next, BT_WRITE);
18921894
spage = BufferGetPage(sbuf);
18931895
sopaque = BTPageGetOpaque(spage);
18941896
if (sopaque->btpo_prev != origpagenumber)
@@ -2102,6 +2104,8 @@ _bt_insert_parent(Relation rel,
21022104
bool isroot,
21032105
bool isonly)
21042106
{
2107+
Assert(heaprel != NULL);
2108+
21052109
/*
21062110
* Here we have to do something Lehman and Yao don't talk about: deal with
21072111
* a root split and construction of a new root. If our stack is empty
@@ -2121,8 +2125,8 @@ _bt_insert_parent(Relation rel,
21212125

21222126
Assert(stack == NULL);
21232127
Assert(isonly);
2124-
/* create a new root node and update the metapage */
2125-
rootbuf = _bt_newroot(rel, heaprel, buf, rbuf);
2128+
/* create a new root node one level up and update the metapage */
2129+
rootbuf = _bt_newlevel(rel, heaprel, buf, rbuf);
21262130
/* release the split buffers */
21272131
_bt_relbuf(rel, rootbuf);
21282132
_bt_relbuf(rel, rbuf);
@@ -2161,8 +2165,7 @@ _bt_insert_parent(Relation rel,
21612165
BlockNumberIsValid(RelationGetTargetBlock(rel))));
21622166

21632167
/* Find the leftmost page at the next level up */
2164-
pbuf = _bt_get_endpoint(rel, heaprel, opaque->btpo_level + 1, false,
2165-
NULL);
2168+
pbuf = _bt_get_endpoint(rel, opaque->btpo_level + 1, false, NULL);
21662169
/* Set up a phony stack entry pointing there */
21672170
stack = &fakestack;
21682171
stack->bts_blkno = BufferGetBlockNumber(pbuf);
@@ -2230,6 +2233,9 @@ _bt_insert_parent(Relation rel,
22302233
*
22312234
* On entry, 'lbuf' must be locked in write-mode. On exit, it is unlocked
22322235
* and unpinned.
2236+
*
2237+
* Caller must provide a valid heaprel, since finishing a page split requires
2238+
* allocating a new page if and when the parent page splits in turn.
22332239
*/
22342240
void
22352241
_bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
@@ -2243,9 +2249,10 @@ _bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
22432249
bool wasonly;
22442250

22452251
Assert(P_INCOMPLETE_SPLIT(lpageop));
2252+
Assert(heaprel != NULL);
22462253

22472254
/* Lock right sibling, the one missing the downlink */
2248-
rbuf = _bt_getbuf(rel, heaprel, lpageop->btpo_next, BT_WRITE);
2255+
rbuf = _bt_getbuf(rel, lpageop->btpo_next, BT_WRITE);
22492256
rpage = BufferGetPage(rbuf);
22502257
rpageop = BTPageGetOpaque(rpage);
22512258

@@ -2257,7 +2264,7 @@ _bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
22572264
BTMetaPageData *metad;
22582265

22592266
/* acquire lock on the metapage */
2260-
metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
2267+
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
22612268
metapg = BufferGetPage(metabuf);
22622269
metad = BTPageGetMeta(metapg);
22632270

@@ -2323,10 +2330,11 @@ _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child
23232330
Page page;
23242331
BTPageOpaque opaque;
23252332

2326-
buf = _bt_getbuf(rel, heaprel, blkno, BT_WRITE);
2333+
buf = _bt_getbuf(rel, blkno, BT_WRITE);
23272334
page = BufferGetPage(buf);
23282335
opaque = BTPageGetOpaque(page);
23292336

2337+
Assert(heaprel != NULL);
23302338
if (P_INCOMPLETE_SPLIT(opaque))
23312339
{
23322340
_bt_finish_split(rel, heaprel, buf, stack->bts_parent);
@@ -2415,7 +2423,7 @@ _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child
24152423
}
24162424

24172425
/*
2418-
* _bt_newroot() -- Create a new root page for the index.
2426+
* _bt_newlevel() -- Create a new level above root page.
24192427
*
24202428
* We've just split the old root page and need to create a new one.
24212429
* In order to do this, we add a new root page to the file, then lock
@@ -2433,7 +2441,7 @@ _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child
24332441
* lbuf, rbuf & rootbuf.
24342442
*/
24352443
static Buffer
2436-
_bt_newroot(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
2444+
_bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
24372445
{
24382446
Buffer rootbuf;
24392447
Page lpage,
@@ -2459,12 +2467,12 @@ _bt_newroot(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
24592467
lopaque = BTPageGetOpaque(lpage);
24602468

24612469
/* get a new root page */
2462-
rootbuf = _bt_getbuf(rel, heaprel, P_NEW, BT_WRITE);
2470+
rootbuf = _bt_allocbuf(rel, heaprel);
24632471
rootpage = BufferGetPage(rootbuf);
24642472
rootblknum = BufferGetBlockNumber(rootbuf);
24652473

24662474
/* acquire lock on the metapage */
2467-
metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
2475+
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
24682476
metapg = BufferGetPage(metabuf);
24692477
metad = BTPageGetMeta(metapg);
24702478

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy