]> granicus.if.org Git - postgresql/commitdiff
Fix duplicating ROOT page in concurrent updates.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 22 Apr 1999 08:19:59 +0000 (08:19 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
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))
                {