From 598a12722ac117bb0286c0a614274bf6763f1c43 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Mon, 29 Jan 2001 07:28:17 +0000
Subject: [PATCH] Call _bt_fixroot() from _bt_insertonpg.

---
 src/backend/access/nbtree/nbtinsert.c | 62 +++++++++++++++++++++++++--
 src/backend/access/nbtree/nbtpage.c   |  3 +-
 2 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 8f23e16992a..76d2d9ff869 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -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.
  *
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 0f68a066dc7..eb9ad9b9dd2 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -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);
-- 
GitLab