88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.62 2000/08/25 23:13:33 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.63 2000/10/04 00:04:42 vadim Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -33,6 +33,7 @@ typedef struct
3333int best_delta ;/* best size delta so far */
3434}FindSplitData ;
3535
36+ void _bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf );
3637
3738static TransactionId _bt_check_unique (Relation rel ,BTItem btitem ,
3839Relation heapRel ,Buffer buf ,
@@ -54,7 +55,6 @@ static void _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
5455int leftfree ,int rightfree ,
5556bool newitemonleft ,Size firstrightitemsz );
5657static Buffer _bt_getstackbuf (Relation rel ,BTStack stack );
57- static void _bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf );
5858static void _bt_pgaddtup (Relation rel ,Page page ,
5959Size itemsize ,BTItem btitem ,
6060OffsetNumber itup_off ,const char * where );
@@ -514,6 +514,29 @@ _bt_insertonpg(Relation rel,
514514}
515515else
516516{
517+ #ifdef XLOG
518+ /* XLOG stuff */
519+ {
520+ char xlbuf [sizeof (xl_btree_insert )+ 2 * sizeof (CommandId )];
521+ xl_btree_insert * xlrec = xlbuf ;
522+ int hsize = SizeOfBtreeInsert ;
523+
524+ xlrec -> target .node = rel -> rd_node ;
525+ ItemPointerSet (& (xlrec -> target .tid ),BufferGetBlockNumber (buf ),newitemoff );
526+ if (P_ISLEAF (lpageop ))
527+ {
528+ CommandId cid = GetCurrentCommandId ();
529+ memcpy (xlbuf + SizeOfBtreeInsert ,& (char * )cid ,sizeof (CommandId ));
530+ hsize += sizeof (CommandId );
531+ }
532+
533+ XLogRecPtr recptr = XLogInsert (RM_BTREE_ID ,XLOG_BTREE_INSERT ,
534+ xlbuf ,hsize , (char * )btitem ,itemsz );
535+
536+ PageSetLSN (page ,recptr );
537+ PageSetSUI (page ,ThisStartUpID );
538+ }
539+ #endif
517540_bt_pgaddtup (rel ,page ,itemsz ,btitem ,newitemoff ,"page" );
518541itup_off = newitemoff ;
519542itup_blkno = BufferGetBlockNumber (buf );
@@ -578,8 +601,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
578601ropaque = (BTPageOpaque )PageGetSpecialPointer (rightpage );
579602
580603/* if we're splitting this page, it won't be the root when we're done */
581- oopaque -> btpo_flags &= ~BTP_ROOT ;
582- lopaque -> btpo_flags = ropaque -> btpo_flags = oopaque -> btpo_flags ;
604+ lopaque -> btpo_flags = oopaque -> btpo_flags ;
605+ lopaque -> btpo_flags &= ~BTP_ROOT ;
606+ ropaque -> btpo_flags = lopaque -> btpo_flags ;
583607lopaque -> btpo_prev = oopaque -> btpo_prev ;
584608lopaque -> btpo_next = BufferGetBlockNumber (rbuf );
585609ropaque -> btpo_prev = BufferGetBlockNumber (buf );
@@ -608,7 +632,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
608632item = (BTItem )PageGetItem (origpage ,itemid );
609633if (PageAddItem (rightpage , (Item )item ,itemsz ,rightoff ,
610634LP_USED )== InvalidOffsetNumber )
611- elog (FATAL ,"btree: failed to add hikey to the right sibling" );
635+ elog (STOP ,"btree: failed to add hikey to the right sibling" );
612636rightoff = OffsetNumberNext (rightoff );
613637}
614638
@@ -633,7 +657,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
633657}
634658if (PageAddItem (leftpage , (Item )item ,itemsz ,leftoff ,
635659LP_USED )== InvalidOffsetNumber )
636- elog (FATAL ,"btree: failed to add hikey to the left sibling" );
660+ elog (STOP ,"btree: failed to add hikey to the left sibling" );
637661leftoff = OffsetNumberNext (leftoff );
638662
639663/*
@@ -704,6 +728,75 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
704728}
705729}
706730
731+ /*
732+ * We have to grab the right sibling (if any) and fix the prev
733+ * pointer there. We are guaranteed that this is deadlock-free
734+ * since no other writer will be holding a lock on that page
735+ * and trying to move left, and all readers release locks on a page
736+ * before trying to fetch its neighbors.
737+ */
738+
739+ if (!P_RIGHTMOST (ropaque ))
740+ {
741+ sbuf = _bt_getbuf (rel ,ropaque -> btpo_next ,BT_WRITE );
742+ spage = BufferGetPage (sbuf );
743+ }
744+
745+ #ifdef XLOG
746+ /*
747+ * Right sibling is locked, new siblings are prepared, but original
748+ * page is not updated yet. Log changes before continuing.
749+ *
750+ * NO ELOG(ERROR) till right sibling is updated.
751+ *
752+ */
753+ {
754+ char xlbuf [sizeof (xl_btree_split )+
755+ 2 * sizeof (CommandId )+ BLCKSZ ];
756+ xl_btree_split * xlrec = xlbuf ;
757+ int hsize = SizeOfBtreeSplit ;
758+ int flag = (newitemonleft ) ?
759+ XLOG_BTREE_SPLEFT :XLOG_BTREE_SPLIT ;
760+
761+ xlrec -> target .node = rel -> rd_node ;
762+ ItemPointerSet (& (xlrec -> target .tid ),itup_blkno ,itup_off );
763+ if (P_ISLEAF (lopaque ))
764+ {
765+ CommandId cid = GetCurrentCommandId ();
766+ memcpy (xlbuf + hsize ,& (char * )cid ,sizeof (CommandId ));
767+ hsize += sizeof (CommandId );
768+ }
769+ if (newitemonleft )
770+ {
771+ memcpy (xlbuf + hsize , (char * )newitem ,newitemsz );
772+ hsize += newitemsz ;
773+ xlrec -> otherblk = BufferGetBlockNumber (rbuf );
774+ }
775+ else
776+ xlrec -> otherblk = BufferGetBlockNumber (buf );
777+
778+ xlrec -> rightblk = ropaque -> btpo_next ;
779+
780+ /*
781+ * Dirrect access to page is not good but faster - we should
782+ * implement some new func in page API.
783+ */
784+ XLogRecPtr recptr = XLogInsert (RM_BTREE_ID ,flag ,xlbuf ,
785+ hsize , (char * )rightpage + (PageHeader )rightpage )-> pd_upper ,
786+ ((PageHeader )rightpage )-> pd_special - ((PageHeader )rightpage )-> upper );
787+
788+ PageSetLSN (leftpage ,recptr );
789+ PageSetSUI (leftpage ,ThisStartUpID );
790+ PageSetLSN (rightpage ,recptr );
791+ PageSetSUI (rightpage ,ThisStartUpID );
792+ if (!P_RIGHTMOST (ropaque ))
793+ {
794+ PageSetLSN (spage ,recptr );
795+ PageSetSUI (spage ,ThisStartUpID );
796+ }
797+ }
798+ #endif
799+
707800/*
708801 * By here, the original data page has been split into two new halves,
709802 * and these are correct. The algorithm requires that the left page
@@ -716,18 +809,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
716809
717810PageRestoreTempPage (leftpage ,origpage );
718811
719- /*
720- * Finally, we need to grab the right sibling (if any) and fix the
721- * prev pointer there.We are guaranteed that this is deadlock-free
722- * since no other writer will be holding a lock on that page
723- * and trying to move left, and all readers release locks on a page
724- * before trying to fetch its neighbors.
725- */
726-
727812if (!P_RIGHTMOST (ropaque ))
728813{
729- sbuf = _bt_getbuf (rel ,ropaque -> btpo_next ,BT_WRITE );
730- spage = BufferGetPage (sbuf );
731814sopaque = (BTPageOpaque )PageGetSpecialPointer (spage );
732815sopaque -> btpo_prev = BufferGetBlockNumber (rbuf );
733816
@@ -1002,7 +1085,7 @@ _bt_getstackbuf(Relation rel, BTStack stack)
10021085 *two new children. The new root page is neither pinned nor locked, and
10031086 *we have also written out lbuf and rbuf and dropped their pins/locks.
10041087 */
1005- static void
1088+ void
10061089_bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf )
10071090{
10081091Buffer rootbuf ;
@@ -1011,7 +1094,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
10111094rootpage ;
10121095BlockNumber lbkno ,
10131096rbkno ;
1014- BlockNumber rootbknum ;
1097+ BlockNumber rootblknum ;
10151098BTPageOpaque rootopaque ;
10161099ItemId itemid ;
10171100BTItem item ;
@@ -1021,12 +1104,16 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
10211104/* get a new root page */
10221105rootbuf = _bt_getbuf (rel ,P_NEW ,BT_WRITE );
10231106rootpage = BufferGetPage (rootbuf );
1024- rootbknum = BufferGetBlockNumber (rootbuf );
1107+ rootblknum = BufferGetBlockNumber (rootbuf );
1108+
1109+
1110+ /* NO ELOG(ERROR) from here till newroot op is logged */
10251111
10261112/* set btree special data */
10271113rootopaque = (BTPageOpaque )PageGetSpecialPointer (rootpage );
10281114rootopaque -> btpo_prev = rootopaque -> btpo_next = P_NONE ;
10291115rootopaque -> btpo_flags |=BTP_ROOT ;
1116+ rootopaque -> btpo_parent = BTREE_METAPAGE ;
10301117
10311118lbkno = BufferGetBlockNumber (lbuf );
10321119rbkno = BufferGetBlockNumber (rbuf );
@@ -1040,7 +1127,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
10401127 */
10411128((BTPageOpaque )PageGetSpecialPointer (lpage ))-> btpo_parent =
10421129((BTPageOpaque )PageGetSpecialPointer (rpage ))-> btpo_parent =
1043- rootbknum ;
1130+ rootblknum ;
10441131
10451132/*
10461133 * Create downlink item for left page (old root). Since this will be
@@ -1058,7 +1145,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
10581145 * the two items will go into positions P_HIKEY and P_FIRSTKEY.
10591146 */
10601147if (PageAddItem (rootpage , (Item )new_item ,itemsz ,P_HIKEY ,LP_USED )== InvalidOffsetNumber )
1061- elog (FATAL ,"btree: failed to add leftkey to new root page" );
1148+ elog (STOP ,"btree: failed to add leftkey to new root page" );
10621149pfree (new_item );
10631150
10641151/*
@@ -1075,14 +1162,35 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
10751162 * insert the right page pointer into the new root page.
10761163 */
10771164if (PageAddItem (rootpage , (Item )new_item ,itemsz ,P_FIRSTKEY ,LP_USED )== InvalidOffsetNumber )
1078- elog (FATAL ,"btree: failed to add rightkey to new root page" );
1165+ elog (STOP ,"btree: failed to add rightkey to new root page" );
10791166pfree (new_item );
10801167
1168+ #ifdef XLOG
1169+ /* XLOG stuff */
1170+ {
1171+ xl_btree_newroot xlrec ;
1172+ xlrec .node = rel -> rd_node ;
1173+ xlrec .rootblk = rootblknum ;
1174+
1175+ /*
1176+ * Dirrect access to page is not good but faster - we should
1177+ * implement some new func in page API.
1178+ */
1179+ XLogRecPtr recptr = XLogInsert (RM_BTREE_ID ,XLOG_BTREE_NEWROOT ,
1180+ & xlrec ,SizeOfBtreeNewroot ,
1181+ (char * )rootpage + (PageHeader )rootpage )-> pd_upper ,
1182+ ((PageHeader )rootpage )-> pd_special - ((PageHeader )rootpage )-> upper );
1183+
1184+ PageSetLSN (rootpage ,recptr );
1185+ PageSetSUI (rootpage ,ThisStartUpID );
1186+ }
1187+ #endif
1188+
10811189/* write and let go of the new root buffer */
10821190_bt_wrtbuf (rel ,rootbuf );
10831191
10841192/* update metadata page with new root block number */
1085- _bt_metaproot (rel ,rootbknum ,0 );
1193+ _bt_metaproot (rel ,rootblknum ,0 );
10861194
10871195/* update and release new sibling, and finally the old root */
10881196_bt_wrtbuf (rel ,rbuf );
@@ -1125,7 +1233,7 @@ _bt_pgaddtup(Relation rel,
11251233
11261234if (PageAddItem (page , (Item )btitem ,itemsize ,itup_off ,
11271235LP_USED )== InvalidOffsetNumber )
1128- elog (FATAL ,"btree: failed to add item to the %s for %s" ,
1236+ elog (STOP ,"btree: failed to add item to the %s for %s" ,
11291237where ,RelationGetRelationName (rel ));
11301238}
11311239