8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.77 2001/01/26 01:24:31 vadim Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.78 2001/01/29 07:28:16 vadim Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -34,7 +34,10 @@ typedef struct
34
34
int best_delta ; /* best size delta so far */
35
35
} FindSplitData ;
36
36
37
+ extern bool FixBTree ;
38
+
37
39
Buffer _bt_fixroot (Relation rel , Buffer oldrootbuf , bool release );
40
+ static void _bt_fixtree (Relation rel , BlockNumber blkno , BTStack stack );
38
41
39
42
static Buffer _bt_newroot (Relation rel , Buffer lbuf , Buffer rbuf );
40
43
@@ -477,10 +480,55 @@ _bt_insertonpg(Relation rel,
477
480
BTItem ritem ;
478
481
Buffer pbuf ;
479
482
480
- /* Set up a phony stack entry if we haven't got a real one */
483
+ /* If root page was splitted */
481
484
if (stack == (BTStack ) NULL )
482
485
{
483
486
elog (DEBUG , "btree: concurrent ROOT page split" );
487
+ /*
488
+ * If root page splitter failed to create new root page
489
+ * then old root' btpo_parent still points to metapage.
490
+ * We have to fix root page in this case.
491
+ */
492
+ if (lpageop -> btpo_parent == BTREE_METAPAGE )
493
+ {
494
+ if (!FixBTree )
495
+ elog (ERROR , "bt_insertonpg: no root page found" );
496
+ _bt_wrtbuf (rel , rbuf );
497
+ _bt_wrtnorelbuf (rel , buf );
498
+ while (! P_LEFTMOST (lpageop ))
499
+ {
500
+ BlockNumber blkno = lpageop -> btpo_prev ;
501
+ LockBuffer (buf , BUFFER_LOCK_UNLOCK );
502
+ ReleaseBuffer (buf );
503
+ buf = _bt_getbuf (rel , blkno , BT_WRITE );
504
+ page = BufferGetPage (buf );
505
+ lpageop = (BTPageOpaque ) PageGetSpecialPointer (page );
506
+ /*
507
+ * If someone else already created parent pages
508
+ * then it's time for _bt_fixtree() to check upper
509
+ * levels and fix them, if required.
510
+ */
511
+ if (lpageop -> btpo_parent != BTREE_METAPAGE )
512
+ {
513
+ blkno = lpageop -> btpo_parent ;
514
+ _bt_relbuf (rel , buf , BT_WRITE );
515
+ _bt_fixtree (rel , blkno , NULL );
516
+ goto formres ;
517
+ }
518
+ }
519
+ /*
520
+ * Ok, we are on the leftmost page, it's write locked
521
+ * by us and its btpo_parent points to meta page - time
522
+ * for _bt_fixroot().
523
+ */
524
+ buf = _bt_fixroot (rel , buf , true);
525
+ _bt_relbuf (rel , buf , BT_WRITE );
526
+ goto formres ;
527
+ }
528
+
529
+ /*
530
+ * Set up a phony stack entry if we haven't got a real one
531
+ */
484
532
stack = & fakestack ;
485
533
stack -> bts_blkno = lpageop -> btpo_parent ;
486
534
stack -> bts_offset = InvalidOffsetNumber ;
@@ -537,6 +585,7 @@ _bt_insertonpg(Relation rel,
537
585
_bt_wrtbuf (rel , buf );
538
586
}
539
587
588
+ formres :;
540
589
/* by here, the new tuple is inserted at itup_blkno/itup_off */
541
590
res = (InsertIndexResult ) palloc (sizeof (InsertIndexResultData ));
542
591
ItemPointerSet (& (res -> pointerData ), itup_blkno , itup_off );
@@ -1414,8 +1463,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
1414
1463
* created with _bt_newroot() - rootbuf, - and buf we've used
1415
1464
* for last insert ops - buf. If rootbuf != buf then we have to
1416
1465
* create at least one more level. And if "release" is TRUE
1417
- * (ie we've already created some levels) then we give up
1418
- * oldrootbuf.
1466
+ * then we give up oldrootbuf.
1419
1467
*/
1420
1468
if (release )
1421
1469
_bt_relbuf (rel , oldrootbuf , BT_WRITE );
@@ -1429,6 +1477,12 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
1429
1477
return (rootbuf );
1430
1478
}
1431
1479
1480
+ static void
1481
+ _bt_fixtree (Relation rel , BlockNumber blkno , BTStack stack )
1482
+ {
1483
+ elog (ERROR , "bt_fixtree: unimplemented , yet" );
1484
+ }
1485
+
1432
1486
/*
1433
1487
* _bt_pgaddtup() -- add a tuple to a particular page in the index.
1434
1488
*
0 commit comments