From 3888b53a58e474cbb2b38d5e84b4b749b1caa663 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Thu, 22 Apr 1999 08:19:59 +0000 Subject: [PATCH] Fix duplicating ROOT page in concurrent updates. --- src/backend/access/nbtree/nbtinsert.c | 16 +++++++++-- src/backend/access/nbtree/nbtpage.c | 41 ++++++++++++++++++--------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 308aa9e9a6d..23ff4262d50 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -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); diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 0cace9d360e..daff4e6bdd4 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -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)) {