@ -1951,6 +1951,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
*/
*/
itemid = PageGetItemId ( page , P_HIKEY ) ;
itemid = PageGetItemId ( page , P_HIKEY ) ;
leafhikey = ( IndexTuple ) PageGetItem ( page , itemid ) ;
leafhikey = ( IndexTuple ) PageGetItem ( page , itemid ) ;
target = BTreeTupleGetTopParent ( leafhikey ) ;
leafleftsib = opaque - > btpo_prev ;
leafleftsib = opaque - > btpo_prev ;
leafrightsib = opaque - > btpo_next ;
leafrightsib = opaque - > btpo_next ;
@ -1965,21 +1966,29 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
/*
/*
* If the leaf page still has a parent pointing to it ( or a chain of
* If the leaf page still has a parent pointing to it ( or a chain of
* parents ) , we don ' t unlink the leaf page yet , but the topmost remaining
* parents ) , we don ' t unlink the leaf page yet , but the topmost remaining
* parent in the branch . Set ' target ' and ' buf ' to reference the page
* parent in the branch ( i . e . the " top parent " )
* actually being unlinked .
*/
*/
target = BTreeTupleGetTopParent ( leafhikey ) ;
if ( ! BlockNumberIsValid ( target ) )
{
/* No top parent, so target is leaf page */
target = leafblkno ;
if ( target ! = InvalidBlockNumber )
buf = leafbuf ;
leftsib = leafleftsib ;
targetlevel = 0 ;
}
else
{
{
/* Target is the internal page taken from leaf's top parent */
Assert ( target ! = leafblkno ) ;
Assert ( target ! = leafblkno ) ;
/* fetch the block number of the topmost parent's left sibling */
/* Fetch the block number of the targe t's left sibling */
buf = _bt_getbuf ( rel , target , BT_READ ) ;
buf = _bt_getbuf ( rel , target , BT_READ ) ;
page = BufferGetPage ( buf ) ;
page = BufferGetPage ( buf ) ;
opaque = ( BTPageOpaque ) PageGetSpecialPointer ( page ) ;
opaque = ( BTPageOpaque ) PageGetSpecialPointer ( page ) ;
leftsib = opaque - > btpo_prev ;
leftsib = opaque - > btpo_prev ;
targetlevel = opaque - > btpo . level ;
targetlevel = opaque - > btpo . level ;
Assert ( targetlevel > 0 ) ;
/*
/*
* To avoid deadlocks , we ' d better drop the target page lock before
* To avoid deadlocks , we ' d better drop the target page lock before
@ -1987,14 +1996,6 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
*/
*/
LockBuffer ( buf , BUFFER_LOCK_UNLOCK ) ;
LockBuffer ( buf , BUFFER_LOCK_UNLOCK ) ;
}
}
else
{
target = leafblkno ;
buf = leafbuf ;
leftsib = leafleftsib ;
targetlevel = 0 ;
}
/*
/*
* We have to lock the pages we need to modify in the standard order :
* We have to lock the pages we need to modify in the standard order :
@ -2181,6 +2182,12 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
* If we deleted a parent of the targeted leaf page , instead of the leaf
* If we deleted a parent of the targeted leaf page , instead of the leaf
* itself , update the leaf to point to the next remaining child in the
* itself , update the leaf to point to the next remaining child in the
* branch .
* branch .
*
* Note : We rely on the fact that a buffer pin on the leaf page has been
* held since leafhikey was initialized . This is safe , though only
* because the page was already half - dead at that point . The leaf page
* cannot have been modified by any other backend during the period when
* no lock was held .
*/
*/
if ( target ! = leafblkno )
if ( target ! = leafblkno )
BTreeTupleSetTopParent ( leafhikey , nextchild ) ;
BTreeTupleSetTopParent ( leafhikey , nextchild ) ;