Fix duplicating ROOT page in concurrent updates.
authorVadim B. Mikheev
Thu, 22 Apr 1999 08:19:59 +0000 (08:19 +0000)
committerVadim B. Mikheev
Thu, 22 Apr 1999 08:19:59 +0000 (08:19 +0000)
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtpage.c

index 308aa9e9a6dd4f594671b008e1318571d9a43697..23ff4262d50e8d97cd60e328237c9a97ff561589 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.37 1999/04/12 16:56:08 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.38 1999/04/22 08:19:59 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -398,6 +398,7 @@ _bt_insertonpg(Relation rel,
        OffsetNumber maxoff;
        bool        shifted = false;
        bool        left_chained = (lpageop->btpo_flags & BTP_CHAIN) ? true : false;
+       bool        is_root = lpageop->btpo_flags & BTP_ROOT;
 
        /*
         * If we have to split leaf page in the chain of duplicates by new
@@ -570,9 +571,20 @@ _bt_insertonpg(Relation rel,
         * reasoning).
         */
 
+l_spl:;
        if (stack == (BTStack) NULL)
        {
-
+           if (!is_root)   /* if this page was not root page */
+           {
+               elog(DEBUG, "btree: concurrent ROOT page split");
+               stack = (BTStack) palloc(sizeof(BTStackData));
+               stack->bts_blkno = lpageop->btpo_parent;
+               stack->bts_offset = InvalidOffsetNumber;
+               stack->bts_btitem = (BTItem) palloc(sizeof(BTItemData));
+               /* bts_btitem will be initialized below */
+               stack->bts_parent = NULL;
+               goto l_spl;
+           }
            /* create a new root node and release the split buffers */
            _bt_newroot(rel, buf, rbuf);
            _bt_relbuf(rel, buf, BT_WRITE);
index 0cace9d360e2e3fc761db5ca03817febe8d4cdb5..daff4e6bdd4f3f347da17d1f137059646014f2da 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.19 1999/03/28 20:31:57 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.20 1999/04/22 08:19:59 vadim Exp $
  *
  * NOTES
  *    Postgres btree pages look like ordinary relation pages.  The opaque
@@ -494,24 +494,37 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
    opaque = (BTPageOpaque) PageGetSpecialPointer(page);
    maxoff = PageGetMaxOffsetNumber(page);
 
-   if (maxoff >= stack->bts_offset)
+   if (stack->bts_offset == InvalidOffsetNumber || 
+       maxoff >= stack->bts_offset)
    {
-       itemid = PageGetItemId(page, stack->bts_offset);
-       item = (BTItem) PageGetItem(page, itemid);
-
-       /* if the item is where we left it, we're done */
-       if (BTItemSame(item, stack->bts_btitem))
+       /*
+        * _bt_insertonpg set bts_offset to InvalidOffsetNumber
+        * in the case of concurrent ROOT page split
+        */
+       if (stack->bts_offset == InvalidOffsetNumber)
        {
-           pfree(stack->bts_btitem);
-           item_nbytes = ItemIdGetLength(itemid);
-           item_save = (BTItem) palloc(item_nbytes);
-           memmove((char *) item_save, (char *) item, item_nbytes);
-           stack->bts_btitem = item_save;
-           return buf;
+           i = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY;
+       }
+       else
+       {
+           itemid = PageGetItemId(page, stack->bts_offset);
+           item = (BTItem) PageGetItem(page, itemid);
+
+           /* if the item is where we left it, we're done */
+           if (BTItemSame(item, stack->bts_btitem))
+           {
+               pfree(stack->bts_btitem);
+               item_nbytes = ItemIdGetLength(itemid);
+               item_save = (BTItem) palloc(item_nbytes);
+               memmove((char *) item_save, (char *) item, item_nbytes);
+               stack->bts_btitem = item_save;
+               return buf;
+           }
+           i = OffsetNumberNext(stack->bts_offset);
        }
 
        /* if the item has just moved right on this page, we're done */
-       for (i = OffsetNumberNext(stack->bts_offset);
+       for ( ;
             i <= maxoff;
             i = OffsetNumberNext(i))
        {