Re: PageGetMaxOffsetNumber

Поиск
Список
Период
Сортировка
От Alvaro Herrera
Тема Re: PageGetMaxOffsetNumber
Дата
Msg-id 20021216030520.GA30674@dcc.uchile.cl
обсуждение исходный текст
Ответ на PageGetMaxOffsetNumber  (Alvaro Herrera <alvherre@dcc.uchile.cl>)
Ответы Re: PageGetMaxOffsetNumber  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-hackers
On Sun, Dec 15, 2002 at 11:49:57PM -0300, Alvaro Herrera wrote:

> I iterate over the elements of the parent page in a for loop, and the
> upper bound is rarely reached because the item is found.  However
> sometimes the item isn't found, and PageGetItem fails its assertion
> because the item isn't used (LP_USED).  I have found that
> PageGetMaxOffsetNumber (the upper bound) returns a consistent value
> that's far too high (4294967291, 0xFFFFFFFB) and therefore the for loop
> eventually falls out of bounds.

FWIW, the code that is supposed to do this (and appears to work fine on
most cases) is the following.  buf is the page I'm going to free and
pblkno is the BlockNumber of its parent as seen in btpo_parent.

/** Delete the pointer to a child page.  If the parent page is empty after* the deletion, delete the pointer from its
parenttoo.*/
 
static void
_bt_deletefromparent(Relation rel, BlockNumber pblkno, Buffer buf)
{Buffer            pbuf;OffsetNumber    offnum;Page            ppage;BTPageOpaque    pop;BlockNumber        blkno =
BufferGetBlockNumber(buf),               max;
 
pbuf = _bt_getbuf(rel, pblkno, BT_WRITE);Assert(!BufferIsInvalid(pbuf));
ppage = BufferGetPage(pbuf);pop = (BTPageOpaque) PageGetSpecialPointer(ppage);
/* * Repeat until the correct parent page is found.    Splits may * cause the parent page to move right. */for (;;){
BlockNumber   next;
 
    /* Make sure no one else tries to look at the page. */    LockBuffer(pbuf, BUFFER_LOCK_UNLOCK);
LockBufferForCleanup(pbuf);   max = PageGetMaxOffsetNumber(pop);
 
    /*     * Look every offset of the page for the item pointing to the     * dead page.     */    for (offnum =
FirstOffsetNumber;offnum <= max; offnum++)    {        BTItem            item;        ItemPointer        iptr;
 
        item = (BTItem) PageGetItem(ppage, PageGetItemId(ppage, offnum));        iptr  = &(item->bti_itup.t_tid);
if (ItemPointerGetBlockNumber(iptr) == blkno)        {            /* Ok, we found the page.  Now delete the pointer. */
          ItemPointer        iptrd = palloc(SizeOfIptrData);
 
            ItemPointerSet(iptrd, pblkno, offnum);            _bt_itemdel(rel, pbuf, iptrd);
_bt_wrtnorelbuf(rel,pbuf);            LockBuffer(pbuf, BUFFER_LOCK_UNLOCK);
 
            /*             * If the parent page is empty after this deletion,             * mark it dead and free it
too.            */            if (_bt_pageisempty(ppage))            {                pop->btpo_flags |= BTP_DEAD;
         _bt_processdead(rel, pbuf);            }            ReleaseBuffer(pbuf);            return;        }    }
 
    /*     * If we just finished scanning the rightmost page of the upper level,     * there's some wrong.     */    if
(P_RIGHTMOST(pop))       elog(ERROR, "Unable to find parent page!");
 
    /* Oops, the parent was split.    Check its right sibling. */    next = pop->btpo_next;    _bt_relbuf(rel, pbuf);
pbuf = _bt_getbuf(rel, next, BT_WRITE);    ppage = BufferGetPage(pbuf);    pop = (BTPageOpaque)
PageGetSpecialPointer(ppage);}
}

-- 
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"Aprende a avergonzarte mas ante ti que ante los demas" (Democrito)


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Alvaro Herrera
Дата:
Сообщение: PageGetMaxOffsetNumber
Следующее
От: Greg Copeland
Дата:
Сообщение: Re: PQnotifies() in 7.3 broken?