@ -240,6 +240,9 @@ ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
return hasVoidPage ;
return hasVoidPage ;
}
}
/*
* Delete a posting tree page .
*/
static void
static void
ginDeletePage ( GinVacuumState * gvs , BlockNumber deleteBlkno , BlockNumber leftBlkno ,
ginDeletePage ( GinVacuumState * gvs , BlockNumber deleteBlkno , BlockNumber leftBlkno ,
BlockNumber parentBlkno , OffsetNumber myoff , bool isParentRoot )
BlockNumber parentBlkno , OffsetNumber myoff , bool isParentRoot )
@ -249,39 +252,35 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
Buffer pBuffer ;
Buffer pBuffer ;
Page page ,
Page page ,
parentPage ;
parentPage ;
BlockNumber rightlink ;
/*
* Lock the pages in the same order as an insertion would , to avoid
* deadlocks : left , then right , then parent .
*/
lBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , leftBlkno ,
RBM_NORMAL , gvs - > strategy ) ;
dBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , deleteBlkno ,
dBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , deleteBlkno ,
RBM_NORMAL , gvs - > strategy ) ;
RBM_NORMAL , gvs - > strategy ) ;
if ( leftBlkno ! = InvalidBlockNumber )
lBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , leftBlkno ,
RBM_NORMAL , gvs - > strategy ) ;
else
lBuffer = InvalidBuffer ;
pBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , parentBlkno ,
pBuffer = ReadBufferExtended ( gvs - > index , MAIN_FORKNUM , parentBlkno ,
RBM_NORMAL , gvs - > strategy ) ;
RBM_NORMAL , gvs - > strategy ) ;
LockBuffer ( lBuffer , GIN_EXCLUSIVE ) ;
LockBuffer ( dBuffer , GIN_EXCLUSIVE ) ;
LockBuffer ( dBuffer , GIN_EXCLUSIVE ) ;
if ( ! isParentRoot ) /* parent is already locked by
if ( ! isParentRoot ) /* parent is already locked by
* LockBufferForCleanup ( ) */
* LockBufferForCleanup ( ) */
LockBuffer ( pBuffer , GIN_EXCLUSIVE ) ;
LockBuffer ( pBuffer , GIN_EXCLUSIVE ) ;
if ( leftBlkno ! = InvalidBlockNumber )
LockBuffer ( lBuffer , GIN_EXCLUSIVE ) ;
START_CRIT_SECTION ( ) ;
START_CRIT_SECTION ( ) ;
if ( leftBlkno ! = InvalidBlockNumber )
/* Unlink the page by changing left sibling's rightlink */
{
page = BufferGetPage ( dBuffer ) ;
BlockNumber rightlink ;
rightlink = GinPageGetOpaque ( page ) - > rightlink ;
page = BufferGetPage ( dBuffer ) ;
page = BufferGetPage ( lBuffer ) ;
rightlink = GinPageGetOpaque ( page ) - > rightlink ;
GinPageGetOpaque ( page ) - > rightlink = rightlink ;
page = BufferGetPage ( lBuffer ) ;
GinPageGetOpaque ( page ) - > rightlink = rightlink ;
}
/* Delete downlink from parent */
parentPage = BufferGetPage ( pBuffer ) ;
parentPage = BufferGetPage ( pBuffer ) ;
# ifdef USE_ASSERT_CHECKING
# ifdef USE_ASSERT_CHECKING
do
do
@ -363,10 +362,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
if ( ! isParentRoot )
if ( ! isParentRoot )
LockBuffer ( pBuffer , GIN_UNLOCK ) ;
LockBuffer ( pBuffer , GIN_UNLOCK ) ;
ReleaseBuffer ( pBuffer ) ;
ReleaseBuffer ( pBuffer ) ;
UnlockReleaseBuffer ( lBuffer ) ;
if ( leftBlkno ! = InvalidBlockNumber )
UnlockReleaseBuffer ( lBuffer ) ;
UnlockReleaseBuffer ( dBuffer ) ;
UnlockReleaseBuffer ( dBuffer ) ;
END_CRIT_SECTION ( ) ;
END_CRIT_SECTION ( ) ;
@ -435,10 +431,9 @@ ginScanToDelete(GinVacuumState *gvs, BlockNumber blkno, bool isRoot,
if ( GinPageGetOpaque ( page ) - > maxoff < FirstOffsetNumber )
if ( GinPageGetOpaque ( page ) - > maxoff < FirstOffsetNumber )
{
{
/* the page is empty */
/* we never delete the left- or rightmost branch */
if ( ! ( me - > leftBlkno = = InvalidBlockNumber & & GinPageRightMost ( page ) ) )
if ( me - > leftBlkno ! = InvalidBlockNumber & & ! GinPageRightMost ( page ) )
{
{
/* we never delete right most branch */
Assert ( ! isRoot ) ;
Assert ( ! isRoot ) ;
ginDeletePage ( gvs , blkno , me - > leftBlkno , me - > parent - > blkno , myoff , me - > parent - > isRoot ) ;
ginDeletePage ( gvs , blkno , me - > leftBlkno , me - > parent - > blkno , myoff , me - > parent - > isRoot ) ;
meDelete = TRUE ;
meDelete = TRUE ;