Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dca0762

Browse files
committed
Couple additional functions to fix tree at runtime.
Need in one more function to handle "my bits moved..." case. FixBTree is still FALSE.
1 parent ed7910e commit dca0762

File tree

1 file changed

+324
-7
lines changed

1 file changed

+324
-7
lines changed

src/backend/access/nbtree/nbtinsert.c

Lines changed: 324 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.78 2001/01/29 07:28:16 vadim Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.79 2001/01/31 01:08:36 vadim Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -37,7 +37,9 @@ typedef struct
3737
extern bool FixBTree;
3838

3939
Buffer _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release);
40-
static void _bt_fixtree(Relation rel, BlockNumber blkno, BTStack stack);
40+
static void _bt_fixtree(Relation rel, BlockNumber blkno);
41+
static BlockNumber _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit);
42+
static OffsetNumber _bt_getoff(Page page, BlockNumber blkno);
4143

4244
static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
4345

@@ -512,7 +514,7 @@ _bt_insertonpg(Relation rel,
512514
{
513515
blkno = lpageop->btpo_parent;
514516
_bt_relbuf(rel, buf, BT_WRITE);
515-
_bt_fixtree(rel, blkno, NULL);
517+
_bt_fixtree(rel, blkno);
516518
goto formres;
517519
}
518520
}
@@ -561,6 +563,10 @@ _bt_insertonpg(Relation rel,
561563

562564
pbuf = _bt_getstackbuf(rel, stack);
563565

566+
if (pbuf == InvalidBuffer)
567+
elog(ERROR, "_bt_getstackbuf: my bits moved right off the end of the world!"
568+
"\n\tRecreate index %s.", RelationGetRelationName(rel));
569+
564570
/* Now we can write and unlock the children */
565571
_bt_wrtbuf(rel, rbuf);
566572
_bt_wrtbuf(rel, buf);
@@ -1172,8 +1178,10 @@ _bt_getstackbuf(Relation rel, BTStack stack)
11721178
}
11731179
/* by here, the item we're looking for moved right at least one page */
11741180
if (P_RIGHTMOST(opaque))
1175-
elog(FATAL, "_bt_getstackbuf: my bits moved right off the end of the world!"
1176-
"\n\tRecreate index %s.", RelationGetRelationName(rel));
1181+
{
1182+
_bt_relbuf(rel, buf, BT_WRITE);
1183+
return(InvalidBuffer);
1184+
}
11771185

11781186
blkno = opaque->btpo_next;
11791187
_bt_relbuf(rel, buf, BT_WRITE);
@@ -1450,6 +1458,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
14501458

14511459
/* give up left buffer */
14521460
_bt_relbuf(rel, leftbuf, BT_WRITE);
1461+
pfree(btitem);
14531462
leftbuf = rightbuf;
14541463
leftpage = rightpage;
14551464
leftopaque = rightopaque;
@@ -1477,10 +1486,318 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
14771486
return(rootbuf);
14781487
}
14791488

1489+
/*
1490+
* Using blkno of leftmost page on a level inside tree this func
1491+
* checks/fixes tree from this level up to the root page.
1492+
*/
14801493
static void
1481-
_bt_fixtree(Relation rel, BlockNumber blkno, BTStack stack)
1494+
_bt_fixtree(Relation rel, BlockNumber blkno)
1495+
{
1496+
Buffer buf;
1497+
Page page;
1498+
BTPageOpaque opaque;
1499+
BlockNumber pblkno;
1500+
1501+
elog(ERROR, "bt_fixtree: unimplemented , yet (need to recreate index)");
1502+
1503+
for ( ; ; )
1504+
{
1505+
buf = _bt_getbuf(rel, blkno, BT_READ);
1506+
page = BufferGetPage(buf);
1507+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1508+
if (! P_LEFTMOST(opaque) || P_ISLEAF(opaque))
1509+
elog(ERROR, "bt_fixtree: invalid start page (need to recreate index)");
1510+
pblkno = opaque->btpo_parent;
1511+
1512+
/* check/fix entire level */
1513+
_bt_fixlevel(rel, buf, InvalidBlockNumber);
1514+
1515+
/*
1516+
* No pins/locks are held here. Re-read start page if its
1517+
* btpo_parent pointed to meta page else go up one level.
1518+
*/
1519+
if (pblkno == BTREE_METAPAGE)
1520+
{
1521+
buf = _bt_getbuf(rel, blkno, BT_WRITE);
1522+
page = BufferGetPage(buf);
1523+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1524+
if (P_ISROOT(opaque))
1525+
{
1526+
/* Tree is Ok now */
1527+
_bt_relbuf(rel, buf, BT_WRITE);
1528+
return;
1529+
}
1530+
pblkno = opaque->btpo_parent;
1531+
/* Call _bt_fixroot() if there is no upper level */
1532+
if (pblkno == BTREE_METAPAGE)
1533+
{
1534+
buf = _bt_fixroot(rel, buf, true);
1535+
_bt_relbuf(rel, buf, BT_WRITE);
1536+
return;
1537+
}
1538+
/* Have to go up one level */
1539+
_bt_relbuf(rel, buf, BT_WRITE);
1540+
blkno = pblkno;
1541+
}
1542+
}
1543+
1544+
}
1545+
1546+
/*
1547+
* Check/fix level starting from page in buffer buf up to block
1548+
* limit on *child* level (or till rightmost child page if limit
1549+
* is InvalidBlockNumber). Start buffer must be read locked.
1550+
* No pins/locks are held on exit. Returns block number of last
1551+
* visited/pointing-to-limit page on *check/fix* level.
1552+
*/
1553+
static BlockNumber
1554+
_bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
1555+
{
1556+
BlockNumber blkno = BufferGetBlockNumber(buf);
1557+
BlockNumber pblkno = blkno;
1558+
Page page;
1559+
BTPageOpaque opaque;
1560+
BlockNumber cblkno[3];
1561+
OffsetNumber coff[3];
1562+
Buffer cbuf[3];
1563+
Page cpage[3];
1564+
BTPageOpaque copaque[3];
1565+
BTItem btitem;
1566+
int cidx, i;
1567+
bool goodbye = false;
1568+
char tbuf[BLCKSZ];
1569+
1570+
page = BufferGetPage(buf);
1571+
/* copy page to temp storage */
1572+
memmove(tbuf, page, PageGetPageSize(page));
1573+
_bt_relbuf(rel, buf, BT_READ);
1574+
1575+
page = (Page)tbuf;
1576+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1577+
1578+
/* Initialize first child data */
1579+
coff[0] = P_FIRSTDATAKEY(opaque);
1580+
if (coff[0] > PageGetMaxOffsetNumber(page))
1581+
elog(ERROR, "bt_fixlevel: invalid maxoff on start page (need to recreate index)");
1582+
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, coff[0]));
1583+
cblkno[0] = ItemPointerGetBlockNumber(&(btitem->bti_itup.t_tid));
1584+
cbuf[0] = _bt_getbuf(rel, cblkno[0], BT_READ);
1585+
cpage[0] = BufferGetPage(cbuf[0]);
1586+
copaque[0] = (BTPageOpaque) PageGetSpecialPointer(cpage[0]);
1587+
if (P_LEFTMOST(opaque) && ! P_LEFTMOST(copaque[0]))
1588+
elog(ERROR, "bt_fixtlevel: non-leftmost child page of leftmost parent (need to recreate index)");
1589+
/* caller should take care and avoid this */
1590+
if (P_RIGHTMOST(copaque[0]))
1591+
elog(ERROR, "bt_fixtlevel: invalid start child (need to recreate index)");
1592+
1593+
for ( ; ; )
1594+
{
1595+
/*
1596+
* Read up to 2 more child pages and look for pointers
1597+
* to them in *saved* parent page
1598+
*/
1599+
coff[1] = coff[2] = InvalidOffsetNumber;
1600+
for (cidx = 0; cidx < 2; )
1601+
{
1602+
cidx++;
1603+
cblkno[cidx] = (copaque[cidx - 1])->btpo_next;
1604+
cbuf[cidx] = _bt_getbuf(rel, cblkno[cidx], BT_READ);
1605+
cpage[cidx] = BufferGetPage(cbuf[cidx]);
1606+
copaque[cidx] = (BTPageOpaque) PageGetSpecialPointer(cpage[cidx]);
1607+
coff[cidx] = _bt_getoff(page, cblkno[cidx]);
1608+
1609+
/* sanity check */
1610+
if (coff[cidx] != InvalidOffsetNumber)
1611+
{
1612+
for (i = cidx - 1; i >= 0; i--)
1613+
{
1614+
if (coff[i] == InvalidOffsetNumber)
1615+
continue;
1616+
if (coff[cidx] != coff[i] + 1)
1617+
elog(ERROR, "bt_fixlevel: invalid item order(1) (need to recreate index)");
1618+
break;
1619+
}
1620+
}
1621+
1622+
if (P_RIGHTMOST(copaque[cidx]))
1623+
break;
1624+
}
1625+
1626+
/*
1627+
* Read parent page and insert missed pointers.
1628+
*/
1629+
if (coff[1] == InvalidOffsetNumber ||
1630+
(cidx == 2 && coff[2] == InvalidOffsetNumber))
1631+
{
1632+
Buffer newbuf;
1633+
Page newpage;
1634+
BTPageOpaque newopaque;
1635+
BTItem ritem;
1636+
Size itemsz;
1637+
OffsetNumber newitemoff;
1638+
BlockNumber parblk[3];
1639+
BTStackData stack;
1640+
1641+
stack.bts_parent = NULL;
1642+
stack.bts_blkno = pblkno;
1643+
stack.bts_offset = InvalidOffsetNumber;
1644+
ItemPointerSet(&(stack.bts_btitem.bti_itup.t_tid),
1645+
cblkno[0], P_HIKEY);
1646+
1647+
buf = _bt_getstackbuf(rel, &stack);
1648+
if (buf == InvalidBuffer)
1649+
elog(ERROR, "bt_fixlevel: pointer disappeared (need to recreate index)");
1650+
1651+
page = BufferGetPage(buf);
1652+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1653+
coff[0] = stack.bts_offset;
1654+
pblkno = BufferGetBlockNumber(buf);
1655+
parblk[0] = pblkno;
1656+
if (cblkno[0] == limit)
1657+
blkno = pblkno; /* where we have seen pointer to limit */
1658+
1659+
/* Check/insert missed pointers */
1660+
for (i = 1; i <= cidx; i++)
1661+
{
1662+
coff[i] = _bt_getoff(page, cblkno[i]);
1663+
1664+
/* sanity check */
1665+
parblk[i] = BufferGetBlockNumber(buf);
1666+
if (coff[i] != InvalidOffsetNumber)
1667+
{
1668+
if (parblk[i] == parblk[i - 1] &&
1669+
coff[i] != coff[i - 1] + 1)
1670+
elog(ERROR, "bt_fixlevel: invalid item order(2) (need to recreate index)");
1671+
if (cblkno[i] == limit)
1672+
blkno = parblk[i];
1673+
continue;
1674+
}
1675+
/* Have to check next page ? */
1676+
if ((! P_RIGHTMOST(opaque)) &&
1677+
coff[i - 1] == PageGetMaxOffsetNumber(page)) /* yes */
1678+
{
1679+
newbuf = _bt_getbuf(rel, opaque->btpo_next, BT_WRITE);
1680+
newpage = BufferGetPage(newbuf);
1681+
newopaque = (BTPageOpaque) PageGetSpecialPointer(newpage);
1682+
coff[i] = _bt_getoff(newpage, cblkno[i]);
1683+
if (coff[i] != InvalidOffsetNumber) /* found ! */
1684+
{
1685+
if (coff[i] != P_FIRSTDATAKEY(newopaque))
1686+
elog(ERROR, "bt_fixlevel: invalid item order(3) (need to recreate index)");
1687+
_bt_relbuf(rel, buf, BT_WRITE);
1688+
buf = newbuf;
1689+
page = newpage;
1690+
opaque = newopaque;
1691+
pblkno = BufferGetBlockNumber(buf);
1692+
parblk[i] = pblkno;
1693+
if (cblkno[i] == limit)
1694+
blkno = pblkno;
1695+
continue;
1696+
}
1697+
/* unfound - need to insert on current page */
1698+
_bt_relbuf(rel, newbuf, BT_WRITE);
1699+
}
1700+
/* insert pointer */
1701+
ritem = (BTItem) PageGetItem(cpage[i - 1],
1702+
PageGetItemId(cpage[i - 1], P_HIKEY));
1703+
btitem = _bt_formitem(&(ritem->bti_itup));
1704+
ItemPointerSet(&(btitem->bti_itup.t_tid), cblkno[i], P_HIKEY);
1705+
itemsz = IndexTupleDSize(btitem->bti_itup)
1706+
+ (sizeof(BTItemData) - sizeof(IndexTupleData));
1707+
itemsz = MAXALIGN(itemsz);
1708+
1709+
newitemoff = coff[i - 1] + 1;
1710+
1711+
if (PageGetFreeSpace(page) < itemsz)
1712+
{
1713+
OffsetNumber firstright;
1714+
OffsetNumber itup_off;
1715+
BlockNumber itup_blkno;
1716+
bool newitemonleft;
1717+
1718+
firstright = _bt_findsplitloc(rel, page,
1719+
newitemoff, itemsz, &newitemonleft);
1720+
newbuf = _bt_split(rel, buf, firstright,
1721+
newitemoff, itemsz, btitem, newitemonleft,
1722+
&itup_off, &itup_blkno);
1723+
/* what buffer we need in ? */
1724+
if (newitemonleft)
1725+
_bt_relbuf(rel, newbuf, BT_WRITE);
1726+
else
1727+
{
1728+
_bt_relbuf(rel, buf, BT_WRITE);
1729+
buf = newbuf;
1730+
page = BufferGetPage(buf);
1731+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1732+
}
1733+
pblkno = BufferGetBlockNumber(buf);
1734+
coff[i] = itup_off;
1735+
}
1736+
else
1737+
{
1738+
_bt_insertuple(rel, buf, itemsz, btitem, newitemoff);
1739+
coff[i] = newitemoff;
1740+
}
1741+
1742+
pfree(btitem);
1743+
parblk[i] = pblkno;
1744+
if (cblkno[i] == limit)
1745+
blkno = pblkno;
1746+
}
1747+
1748+
/* copy page with pointer to cblkno[cidx] to temp storage */
1749+
memmove(tbuf, page, PageGetPageSize(page));
1750+
_bt_relbuf(rel, buf, BT_WRITE);
1751+
page = (Page)tbuf;
1752+
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1753+
if (limit == InvalidBlockNumber)
1754+
blkno = pblkno; /* last visited page */
1755+
}
1756+
1757+
/* Continue if current check/fix level page is rightmost */
1758+
if (P_RIGHTMOST(opaque))
1759+
goodbye = false;
1760+
1761+
/* Pointers to child pages are Ok - right end of child level ? */
1762+
_bt_relbuf(rel, cbuf[0], BT_READ);
1763+
_bt_relbuf(rel, cbuf[1], BT_READ);
1764+
if (cidx == 1 ||
1765+
(cidx == 2 && (P_RIGHTMOST(copaque[2]) || goodbye)))
1766+
{
1767+
if (cidx == 2)
1768+
_bt_relbuf(rel, cbuf[2], BT_READ);
1769+
return(blkno);
1770+
}
1771+
if (cblkno[0] == limit || cblkno[1] == limit)
1772+
goodbye = true;
1773+
cblkno[0] = cblkno[2];
1774+
cbuf[0] = cbuf[2];
1775+
cpage[0] = cpage[2];
1776+
copaque[0] = copaque[2];
1777+
coff[0] = coff[2];
1778+
}
1779+
}
1780+
1781+
static OffsetNumber
1782+
_bt_getoff(Page page, BlockNumber blkno)
14821783
{
1483-
elog(ERROR, "bt_fixtree: unimplemented , yet");
1784+
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
1785+
OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
1786+
OffsetNumber offnum = P_FIRSTDATAKEY(opaque);
1787+
BlockNumber curblkno;
1788+
ItemId itemid;
1789+
BTItem item;
1790+
1791+
for ( ; offnum <= maxoff; offnum++)
1792+
{
1793+
itemid = PageGetItemId(page, offnum);
1794+
item = (BTItem) PageGetItem(page, itemid);
1795+
curblkno = ItemPointerGetBlockNumber(&(item->bti_itup.t_tid));
1796+
if (curblkno == blkno)
1797+
return(offnum);
1798+
}
1799+
1800+
return(InvalidOffsetNumber);
14841801
}
14851802

14861803
/*

0 commit comments

Comments
 (0)