Call _bt_fixroot() from _bt_insertonpg.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Mon, 29 Jan 2001 07:28:17 +0000 (07:28 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Mon, 29 Jan 2001 07:28:17 +0000 (07:28 +0000)
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtpage.c

index 8f23e16992a5013a5baf2c24980b2ebf8740bb2b..76d2d9ff86921ef80c481db7841a1f33dedf3a2e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.77 2001/01/26 01:24:31 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.78 2001/01/29 07:28:16 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,7 +34,10 @@ typedef struct
    int     best_delta;         /* best size delta so far */
 } FindSplitData;
 
+extern bool FixBTree;
+
 Buffer _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release);
+static void _bt_fixtree(Relation rel, BlockNumber blkno, BTStack stack);
 
 static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
 
@@ -477,10 +480,55 @@ _bt_insertonpg(Relation rel,
            BTItem      ritem;
            Buffer      pbuf;
 
-           /* Set up a phony stack entry if we haven't got a real one */
+           /* If root page was splitted */
            if (stack == (BTStack) NULL)
            {
                elog(DEBUG, "btree: concurrent ROOT page split");
+               /*
+                * If root page splitter failed to create new root page
+                * then old root' btpo_parent still points to metapage.
+                * We have to fix root page in this case.
+                */
+               if (lpageop->btpo_parent == BTREE_METAPAGE)
+               {
+                   if (!FixBTree)
+                       elog(ERROR, "bt_insertonpg: no root page found");
+                   _bt_wrtbuf(rel, rbuf);
+                   _bt_wrtnorelbuf(rel, buf);
+                   while(! P_LEFTMOST(lpageop))
+                   {
+                       BlockNumber     blkno = lpageop->btpo_prev;
+                       LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+                       ReleaseBuffer(buf);
+                       buf = _bt_getbuf(rel, blkno, BT_WRITE);
+                       page = BufferGetPage(buf);
+                       lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
+                       /*
+                        * If someone else already created parent pages
+                        * then it's time for _bt_fixtree() to check upper
+                        * levels and fix them, if required.
+                        */
+                       if (lpageop->btpo_parent != BTREE_METAPAGE)
+                       {
+                           blkno = lpageop->btpo_parent;
+                           _bt_relbuf(rel, buf, BT_WRITE);
+                           _bt_fixtree(rel, blkno, NULL);
+                           goto formres;
+                       }
+                   }
+                   /*
+                    * Ok, we are on the leftmost page, it's write locked
+                    * by us and its btpo_parent points to meta page - time
+                    * for _bt_fixroot().
+                    */
+                    buf = _bt_fixroot(rel, buf, true);
+                    _bt_relbuf(rel, buf, BT_WRITE);
+                   goto formres;
+               }
+
+               /*
+                * Set up a phony stack entry if we haven't got a real one
+                */
                stack = &fakestack;
                stack->bts_blkno = lpageop->btpo_parent;
                stack->bts_offset = InvalidOffsetNumber;
@@ -537,6 +585,7 @@ _bt_insertonpg(Relation rel,
        _bt_wrtbuf(rel, buf);
    }
 
+formres:;
    /* by here, the new tuple is inserted at itup_blkno/itup_off */
    res = (InsertIndexResult) palloc(sizeof(InsertIndexResultData));
    ItemPointerSet(&(res->pointerData), itup_blkno, itup_off);
@@ -1414,8 +1463,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
     * created with _bt_newroot() - rootbuf, - and buf we've used
     * for last insert ops - buf. If rootbuf != buf then we have to
     * create at least one more level. And if "release" is TRUE
-    * (ie we've already created some levels) then we give up
-    * oldrootbuf.
+    * then we give up oldrootbuf.
     */
    if (release)
        _bt_relbuf(rel, oldrootbuf, BT_WRITE);
@@ -1429,6 +1477,12 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
    return(rootbuf);
 }
 
+static void
+_bt_fixtree(Relation rel, BlockNumber blkno, BTStack stack)
+{
+   elog(ERROR, "bt_fixtree: unimplemented , yet");
+}
+
 /*
  * _bt_pgaddtup() -- add a tuple to a particular page in the index.
  *
index 0f68a066dc711fcfd543c0cff40b5f2ea3d5722b..eb9ad9b9dd2da56359f619d7c782dab93ca42bda 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.48 2001/01/26 01:24:31 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.49 2001/01/29 07:28:17 vadim Exp $
  *
  * NOTES
  *    Postgres btree pages look like ordinary relation pages.  The opaque
@@ -257,6 +257,7 @@ check_parent:;
                /* handle concurrent fix of root page */
                if (rootopaque->btpo_parent == BTREE_METAPAGE)  /* unupdated! */
                {
+                   elog(NOTICE, "bt_getroot: fixing root page");
                    newrootbuf = _bt_fixroot(rel, rootbuf, true);
                    LockBuffer(newrootbuf, BUFFER_LOCK_UNLOCK);
                    LockBuffer(newrootbuf, BT_READ);