@@ -626,6 +626,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
626626firststack .blkno = GIST_ROOT_BLKNO ;
627627firststack .lsn .xrecoff = 0 ;
628628firststack .parent = NULL ;
629+ firststack .downlinkoffnum = InvalidOffsetNumber ;
629630state .stack = stack = & firststack ;
630631
631632/*
@@ -702,9 +703,10 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
702703BlockNumber childblkno ;
703704IndexTuple newtup ;
704705GISTInsertStack * item ;
706+ OffsetNumber downlinkoffnum ;
705707
706- stack -> childoffnum = gistchoose (state .r ,stack -> page ,itup ,giststate );
707- iid = PageGetItemId (stack -> page ,stack -> childoffnum );
708+ downlinkoffnum = gistchoose (state .r ,stack -> page ,itup ,giststate );
709+ iid = PageGetItemId (stack -> page ,downlinkoffnum );
708710idxtuple = (IndexTuple )PageGetItem (stack -> page ,iid );
709711childblkno = ItemPointerGetBlockNumber (& (idxtuple -> t_tid ));
710712
@@ -754,7 +756,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
754756 * tuple.
755757 */
756758if (gistinserttuples (& state ,stack ,giststate ,& newtup ,1 ,
757- stack -> childoffnum ,InvalidBuffer ))
759+ downlinkoffnum ,InvalidBuffer ))
758760{
759761/*
760762 * If this was a root split, the root page continues to be
@@ -778,6 +780,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
778780item = (GISTInsertStack * )palloc0 (sizeof (GISTInsertStack ));
779781item -> blkno = childblkno ;
780782item -> parent = stack ;
783+ item -> downlinkoffnum = downlinkoffnum ;
781784state .stack = stack = item ;
782785}
783786else
@@ -854,29 +857,37 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
854857/*
855858 * Traverse the tree to find path from root page to specified "child" block.
856859 *
857- * returns from the beginning of closest parent;
860+ * returns a new insertion stack, starting from the parent of "child", up
861+ * to the root. *downlinkoffnum is set to the offset of the downlink in the
862+ * direct parent of child.
858863 *
859864 * To prevent deadlocks, this should lock only one page at a time.
860865 */
861- GISTInsertStack *
862- gistFindPath (Relation r ,BlockNumber child )
866+ static GISTInsertStack *
867+ gistFindPath (Relation r ,BlockNumber child , OffsetNumber * downlinkoffnum )
863868{
864869Page page ;
865870Buffer buffer ;
866871OffsetNumber i ,
867872maxoff ;
868873ItemId iid ;
869874IndexTuple idxtuple ;
875+ List * fifo ;
870876GISTInsertStack * top ,
871- * tail ,
872877* ptr ;
873878BlockNumber blkno ;
874879
875- top = tail = (GISTInsertStack * )palloc0 (sizeof (GISTInsertStack ));
880+ top = (GISTInsertStack * )palloc0 (sizeof (GISTInsertStack ));
876881top -> blkno = GIST_ROOT_BLKNO ;
882+ top -> downlinkoffnum = InvalidOffsetNumber ;
877883
878- while (top && top -> blkno != child )
884+ fifo = list_make1 (top );
885+ while (fifo != NIL )
879886{
887+ /* Get next page to visit */
888+ top = linitial (fifo );
889+ fifo = list_delete_first (fifo );
890+
880891buffer = ReadBuffer (r ,top -> blkno );
881892LockBuffer (buffer ,GIST_SHARE );
882893gistcheckpage (r ,buffer );
@@ -917,12 +928,10 @@ gistFindPath(Relation r, BlockNumber child)
917928 */
918929ptr = (GISTInsertStack * )palloc0 (sizeof (GISTInsertStack ));
919930ptr -> blkno = GistPageGetOpaque (page )-> rightlink ;
920- ptr -> childoffnum = InvalidOffsetNumber ;
931+ ptr -> downlinkoffnum = InvalidOffsetNumber ;
921932ptr -> parent = top -> parent ;
922- ptr -> next = top -> next ;
923- top -> next = ptr ;
924- if (tail == top )
925- tail = ptr ;
933+
934+ fifo = lcons (ptr ,fifo );
926935}
927936
928937maxoff = PageGetMaxOffsetNumber (page );
@@ -934,48 +943,24 @@ gistFindPath(Relation r, BlockNumber child)
934943blkno = ItemPointerGetBlockNumber (& (idxtuple -> t_tid ));
935944if (blkno == child )
936945{
937- OffsetNumber poff = InvalidOffsetNumber ;
938-
939- /* make childs links */
940- ptr = top ;
941- while (ptr -> parent )
942- {
943- /* move childoffnum.. */
944- if (ptr == top )
945- {
946- /* first iteration */
947- poff = ptr -> parent -> childoffnum ;
948- ptr -> parent -> childoffnum = ptr -> childoffnum ;
949- }
950- else
951- {
952- OffsetNumber tmp = ptr -> parent -> childoffnum ;
953-
954- ptr -> parent -> childoffnum = poff ;
955- poff = tmp ;
956- }
957- ptr = ptr -> parent ;
958- }
959- top -> childoffnum = i ;
946+ /* Found it! */
960947UnlockReleaseBuffer (buffer );
948+ * downlinkoffnum = i ;
961949return top ;
962950}
963951else
964952{
965- /*Install next inner page to theend ofstack */
953+ /*Append this child to thelist ofpages to visit later */
966954ptr = (GISTInsertStack * )palloc0 (sizeof (GISTInsertStack ));
967955ptr -> blkno = blkno ;
968- ptr -> childoffnum = i ;/* set offsetnumber of child to child
969- * !!! */
956+ ptr -> downlinkoffnum = i ;
970957ptr -> parent = top ;
971- ptr -> next = NULL ;
972- tail -> next = ptr ;
973- tail = ptr ;
958+
959+ fifo = lappend (fifo ,ptr );
974960}
975961}
976962
977963UnlockReleaseBuffer (buffer );
978- top = top -> next ;
979964}
980965
981966elog (ERROR ,"failed to re-find parent of a page in index \"%s\", block %u" ,
@@ -997,7 +982,7 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
997982parent -> page = (Page )BufferGetPage (parent -> buffer );
998983
999984/* here we don't need to distinguish between split and page update */
1000- if (parent -> childoffnum == InvalidOffsetNumber || !XLByteEQ (parent -> lsn ,PageGetLSN (parent -> page )))
985+ if (child -> downlinkoffnum == InvalidOffsetNumber || !XLByteEQ (parent -> lsn ,PageGetLSN (parent -> page )))
1001986{
1002987/* parent is changed, look child in right links until found */
1003988OffsetNumber i ,
@@ -1016,20 +1001,21 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
10161001if (ItemPointerGetBlockNumber (& (idxtuple -> t_tid ))== child -> blkno )
10171002{
10181003/* yes!!, found */
1019- parent -> childoffnum = i ;
1004+ child -> downlinkoffnum = i ;
10201005return ;
10211006}
10221007}
10231008
10241009parent -> blkno = GistPageGetOpaque (parent -> page )-> rightlink ;
10251010UnlockReleaseBuffer (parent -> buffer );
10261011if (parent -> blkno == InvalidBlockNumber )
1027-
1012+ {
10281013/*
1029- *end of chain and still didn'tfound parent, It's very-very
1030- * rare situation when root splited
1014+ *End of chain and still didn'tfind parent. It's a very-very
1015+ * rare situation when root splited.
10311016 */
10321017break ;
1018+ }
10331019parent -> buffer = ReadBuffer (r ,parent -> blkno );
10341020LockBuffer (parent -> buffer ,GIST_EXCLUSIVE );
10351021gistcheckpage (r ,parent -> buffer );
@@ -1050,7 +1036,7 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
10501036}
10511037
10521038/* ok, find new path */
1053- ptr = parent = gistFindPath (r ,child -> blkno );
1039+ ptr = parent = gistFindPath (r ,child -> blkno , & child -> downlinkoffnum );
10541040
10551041/* read all buffers as expected by caller */
10561042/* note we don't lock them or gistcheckpage them here! */
@@ -1119,7 +1105,7 @@ gistformdownlink(Relation rel, Buffer buf, GISTSTATE *giststate,
11191105
11201106LockBuffer (stack -> parent -> buffer ,GIST_EXCLUSIVE );
11211107gistFindCorrectParent (rel ,stack );
1122- iid = PageGetItemId (stack -> parent -> page ,stack -> parent -> childoffnum );
1108+ iid = PageGetItemId (stack -> parent -> page ,stack -> downlinkoffnum );
11231109downlink = (IndexTuple )PageGetItem (stack -> parent -> page ,iid );
11241110downlink = CopyIndexTuple (downlink );
11251111LockBuffer (stack -> parent -> buffer ,GIST_UNLOCK );
@@ -1147,7 +1133,7 @@ gistfixsplit(GISTInsertState *state, GISTSTATE *giststate)
11471133RelationGetRelationName (state -> r ),stack -> blkno );
11481134
11491135Assert (GistFollowRight (stack -> page ));
1150- Assert (OffsetNumberIsValid (stack -> parent -> childoffnum ));
1136+ Assert (OffsetNumberIsValid (stack -> downlinkoffnum ));
11511137
11521138buf = stack -> buffer ;
11531139
@@ -1284,7 +1270,7 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack,
12841270tuples [1 ]= right -> downlink ;
12851271gistinserttuples (state ,stack -> parent ,giststate ,
12861272tuples ,2 ,
1287- stack -> parent -> childoffnum ,
1273+ stack -> downlinkoffnum ,
12881274left -> buf );
12891275LockBuffer (stack -> parent -> buffer ,GIST_UNLOCK );
12901276UnlockReleaseBuffer (right -> buf );