88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.77 2001/01/26 01:24:31 vadim Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.78 2001/01/29 07:28:16 vadim Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -34,7 +34,10 @@ typedef struct
3434int best_delta ;/* best size delta so far */
3535}FindSplitData ;
3636
37+ extern bool FixBTree ;
38+
3739Buffer _bt_fixroot (Relation rel ,Buffer oldrootbuf ,bool release );
40+ static void _bt_fixtree (Relation rel ,BlockNumber blkno ,BTStack stack );
3841
3942static Buffer _bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf );
4043
@@ -477,10 +480,55 @@ _bt_insertonpg(Relation rel,
477480BTItem ritem ;
478481Buffer pbuf ;
479482
480- /*Set up a phony stack entry if we haven't got a real one */
483+ /*If root page was splitted */
481484if (stack == (BTStack )NULL )
482485{
483486elog (DEBUG ,"btree: concurrent ROOT page split" );
487+ /*
488+ * If root page splitter failed to create new root page
489+ * then old root' btpo_parent still points to metapage.
490+ * We have to fix root page in this case.
491+ */
492+ if (lpageop -> btpo_parent == BTREE_METAPAGE )
493+ {
494+ if (!FixBTree )
495+ elog (ERROR ,"bt_insertonpg: no root page found" );
496+ _bt_wrtbuf (rel ,rbuf );
497+ _bt_wrtnorelbuf (rel ,buf );
498+ while (!P_LEFTMOST (lpageop ))
499+ {
500+ BlockNumber blkno = lpageop -> btpo_prev ;
501+ LockBuffer (buf ,BUFFER_LOCK_UNLOCK );
502+ ReleaseBuffer (buf );
503+ buf = _bt_getbuf (rel ,blkno ,BT_WRITE );
504+ page = BufferGetPage (buf );
505+ lpageop = (BTPageOpaque )PageGetSpecialPointer (page );
506+ /*
507+ * If someone else already created parent pages
508+ * then it's time for _bt_fixtree() to check upper
509+ * levels and fix them, if required.
510+ */
511+ if (lpageop -> btpo_parent != BTREE_METAPAGE )
512+ {
513+ blkno = lpageop -> btpo_parent ;
514+ _bt_relbuf (rel ,buf ,BT_WRITE );
515+ _bt_fixtree (rel ,blkno ,NULL );
516+ gotoformres ;
517+ }
518+ }
519+ /*
520+ * Ok, we are on the leftmost page, it's write locked
521+ * by us and its btpo_parent points to meta page - time
522+ * for _bt_fixroot().
523+ */
524+ buf = _bt_fixroot (rel ,buf , true);
525+ _bt_relbuf (rel ,buf ,BT_WRITE );
526+ gotoformres ;
527+ }
528+
529+ /*
530+ * Set up a phony stack entry if we haven't got a real one
531+ */
484532stack = & fakestack ;
485533stack -> bts_blkno = lpageop -> btpo_parent ;
486534stack -> bts_offset = InvalidOffsetNumber ;
@@ -537,6 +585,7 @@ _bt_insertonpg(Relation rel,
537585_bt_wrtbuf (rel ,buf );
538586}
539587
588+ formres :;
540589/* by here, the new tuple is inserted at itup_blkno/itup_off */
541590res = (InsertIndexResult )palloc (sizeof (InsertIndexResultData ));
542591ItemPointerSet (& (res -> pointerData ),itup_blkno ,itup_off );
@@ -1414,8 +1463,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
14141463 * created with _bt_newroot() - rootbuf, - and buf we've used
14151464 * for last insert ops - buf. If rootbuf != buf then we have to
14161465 * create at least one more level. And if "release" is TRUE
1417- * (ie we've already created some levels) then we give up
1418- * oldrootbuf.
1466+ * then we give up oldrootbuf.
14191467 */
14201468if (release )
14211469_bt_relbuf (rel ,oldrootbuf ,BT_WRITE );
@@ -1429,6 +1477,12 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
14291477return (rootbuf );
14301478}
14311479
1480+ static void
1481+ _bt_fixtree (Relation rel ,BlockNumber blkno ,BTStack stack )
1482+ {
1483+ elog (ERROR ,"bt_fixtree: unimplemented , yet" );
1484+ }
1485+
14321486/*
14331487 *_bt_pgaddtup() -- add a tuple to a particular page in the index.
14341488 *