From 4ce6abc456414345c3d04101776c50504d345768 Mon Sep 17 00:00:00 2001 From: Claudio Freire Date: Wed, 14 Mar 2018 22:15:31 -0300 Subject: [PATCH 2/2] Conditional locks --- src/backend/access/nbtree/nbtinsert.c | 68 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index ab239c4..f9afb4d 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -142,38 +142,54 @@ top: * ensures that the index state cannot change, as far as the rightmost * part of the index is concerned. */ - buf = _bt_getbuf(rel, RelationGetTargetBlock(rel), BT_WRITE); - page = BufferGetPage(buf); + /* buf = _bt_getbuf(rel, RelationGetTargetBlock(rel), BT_WRITE); */ + buf = ReadBuffer(rel, RelationGetTargetBlock(rel)); + + if (ConditionalLockBuffer(buf)) + { + _bt_checkpage(rel, buf); - lpageop = (BTPageOpaque) PageGetSpecialPointer(page); - itemsz = IndexTupleSize(itup); - itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we + page = BufferGetPage(buf); + + lpageop = (BTPageOpaque) PageGetSpecialPointer(page); + itemsz = IndexTupleSize(itup); + itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we * need to be consistent */ - /* - * Check if the page is still the rightmost leaf page, has enough free - * space to accommodate the new tuple, no split is in progress and the - * scankey is greater than or equal to the first key on the page. - */ - if (P_ISLEAF(lpageop) && P_RIGHTMOST(lpageop) && - !P_INCOMPLETE_SPLIT(lpageop) && - !P_IGNORE(lpageop) && - (PageGetFreeSpace(page) > itemsz) && - PageGetMaxOffsetNumber(page) >= P_FIRSTDATAKEY(lpageop) && - _bt_compare(rel, natts, itup_scankey, page, - P_FIRSTDATAKEY(lpageop)) > 0) - { - offset = InvalidOffsetNumber; - fastpath = true; + /* + * Check if the page is still the rightmost leaf page, has enough free + * space to accommodate the new tuple, no split is in progress and the + * scankey is greater than or equal to the first key on the page. + */ + if (P_ISLEAF(lpageop) && P_RIGHTMOST(lpageop) && + !P_INCOMPLETE_SPLIT(lpageop) && + !P_IGNORE(lpageop) && + (PageGetFreeSpace(page) > itemsz) && + PageGetMaxOffsetNumber(page) >= P_FIRSTDATAKEY(lpageop) && + _bt_compare(rel, natts, itup_scankey, page, + P_FIRSTDATAKEY(lpageop)) > 0) + { + offset = InvalidOffsetNumber; + fastpath = true; + } + else + { + _bt_relbuf(rel, buf); + + /* + * Something did not workout. Just forget about the cached block + * and follow the normal path. It might be set again if the + * conditions are favourble. + */ + RelationSetTargetBlock(rel, InvalidBlockNumber); + } } - else - { - _bt_relbuf(rel, buf); + else { + ReleaseBuffer(buf); /* - * Something did not workout. Just forget about the cached block - * and follow the normal path. It might be set again if the - * conditions are favourble. + * If someone's holding a lock, it's likely to change anyway, + * so don't try again until we get an updated rightmost leaf. */ RelationSetTargetBlock(rel, InvalidBlockNumber); } -- 1.8.4.5