summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gist.c')
-rw-r--r--src/backend/access/gist/gist.c483
1 files changed, 384 insertions, 99 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 89ba071355..02c2ffefa2 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.121 2005/06/20 15:22:37 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.122 2005/06/27 12:45:21 teodor Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,6 +23,8 @@
#include "miscadmin.h"
#include "utils/memutils.h"
+const XLogRecPtr XLogRecPtrForTemp = { 1, 1 };
+
/* Working state for gistbuild and its callback */
typedef struct
{
@@ -101,7 +103,7 @@ gistbuild(PG_FUNCTION_ARGS)
initGISTstate(&buildstate.giststate, index);
/* initialize the root page */
- buffer = gistReadBuffer(index, P_NEW);
+ buffer = gistNewBuffer(index);
GISTInitBuffer(buffer, F_LEAF);
if ( !index->rd_istemp ) {
XLogRecPtr recptr;
@@ -122,7 +124,9 @@ gistbuild(PG_FUNCTION_ARGS)
PageSetTLI(page, ThisTimeLineID);
END_CRIT_SECTION();
- }
+ } else
+ PageSetLSN(BufferGetPage(buffer), XLogRecPtrForTemp);
+ LockBuffer(buffer, GIST_UNLOCK);
WriteBuffer(buffer);
/* build the index */
@@ -228,12 +232,6 @@ gistinsert(PG_FUNCTION_ARGS)
MemoryContext oldCtx;
MemoryContext insertCtx;
- /*
- * Since GIST is not marked "amconcurrent" in pg_am, caller should
- * have acquired exclusive lock on index relation. We need no locking
- * here.
- */
-
/* GiST cannot index tuples with leading NULLs */
if (isnull[0])
PG_RETURN_BOOL(false);
@@ -290,8 +288,7 @@ gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
state.key = itup->t_tid;
state.needInsertComplete = true;
- state.stack = (GISTInsertStack*)palloc(sizeof(GISTInsertStack));
- memset( state.stack, 0, sizeof(GISTInsertStack));
+ state.stack = (GISTInsertStack*)palloc0(sizeof(GISTInsertStack));
state.stack->blkno=GIST_ROOT_BLKNO;
gistfindleaf(&state, giststate);
@@ -301,7 +298,19 @@ gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
static bool
gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) {
bool is_splitted = false;
+ bool is_leaf = (GistPageIsLeaf(state->stack->page)) ? true : false;
+
+ if ( !is_leaf )
+ /*
+ * This node's key has been modified, either because a child
+ * split occurred or because we needed to adjust our key for
+ * an insert in a child node. Therefore, remove the old
+ * version of this node's key.
+ */
+
+ PageIndexTupleDelete(state->stack->page, state->stack->childoffnum);
+
if (gistnospace(state->stack->page, state->itup, state->ituplen))
{
/* no space for insertion */
@@ -321,7 +330,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) {
XLogRecData *rdata;
rdata = formSplitRdata(state->r->rd_node, state->stack->blkno,
- &(state->key), state->path, state->pathlen, dist);
+ &(state->key), dist);
START_CRIT_SECTION();
@@ -334,47 +343,106 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) {
}
END_CRIT_SECTION();
- }
-
- ptr = dist;
- while(ptr) {
- WriteBuffer(ptr->buffer);
- ptr=ptr->next;
+ } else {
+ ptr = dist;
+ while(ptr) {
+ PageSetLSN(BufferGetPage(ptr->buffer), XLogRecPtrForTemp);
+ ptr=ptr->next;
+ }
}
state->itup = newitup;
state->ituplen = tlen; /* now tlen >= 2 */
if ( state->stack->blkno == GIST_ROOT_BLKNO ) {
- gistnewroot(state->r, state->itup, state->ituplen, &(state->key));
+ gistnewroot(state->r, state->stack->buffer, state->itup, state->ituplen, &(state->key));
state->needInsertComplete=false;
+ ptr = dist;
+ while(ptr) {
+ Page page = (Page)BufferGetPage(ptr->buffer);
+ GistPageGetOpaque(page)->rightlink = ( ptr->next ) ?
+ ptr->next->block.blkno : InvalidBlockNumber;
+ LockBuffer( ptr->buffer, GIST_UNLOCK );
+ WriteBuffer(ptr->buffer);
+ ptr=ptr->next;
+ }
+ } else {
+ Page page;
+ BlockNumber rightrightlink = InvalidBlockNumber;
+ SplitedPageLayout *ourpage=NULL;
+ GistNSN oldnsn;
+ GISTPageOpaque opaque;
+
+ /* move origpage to first in chain */
+ if ( dist->block.blkno != state->stack->blkno ) {
+ ptr = dist;
+ while(ptr->next) {
+ if ( ptr->next->block.blkno == state->stack->blkno ) {
+ ourpage = ptr->next;
+ ptr->next = ptr->next->next;
+ ourpage->next = dist;
+ dist = ourpage;
+ break;
+ }
+ ptr=ptr->next;
+ }
+ Assert( ourpage != NULL );
+ } else
+ ourpage = dist;
+
+
+ /* now gets all needed data, and sets nsn's */
+ page = (Page)BufferGetPage(ourpage->buffer);
+ opaque = GistPageGetOpaque(page);
+ rightrightlink = opaque->rightlink;
+ oldnsn = opaque->nsn;
+ opaque->nsn = PageGetLSN(page);
+ opaque->rightlink = ourpage->next->block.blkno;
+
+ /* fills and write all new pages.
+ They isn't linked into tree yet */
+
+ ptr = ourpage->next;
+ while(ptr) {
+ page = (Page)BufferGetPage(ptr->buffer);
+ GistPageGetOpaque(page)->rightlink = ( ptr->next ) ?
+ ptr->next->block.blkno : rightrightlink;
+ /* only for last set oldnsn */
+ GistPageGetOpaque(page)->nsn = ( ptr->next ) ?
+ opaque->nsn : oldnsn;
+
+ LockBuffer(ptr->buffer, GIST_UNLOCK);
+ WriteBuffer(ptr->buffer);
+ ptr=ptr->next;
+ }
}
- ReleaseBuffer(state->stack->buffer);
+ WriteNoReleaseBuffer( state->stack->buffer );
}
else
{
/* enough space */
- OffsetNumber off, l;
- bool is_leaf = (GistPageIsLeaf(state->stack->page)) ? true : false;
+ OffsetNumber l, off;
+ XLogRecPtr oldlsn;
- off = (PageIsEmpty(state->stack->page)) ?
- FirstOffsetNumber
- :
- OffsetNumberNext(PageGetMaxOffsetNumber(state->stack->page));
+ off = ( PageIsEmpty(state->stack->page) ) ?
+ FirstOffsetNumber : OffsetNumberNext(PageGetMaxOffsetNumber(state->stack->page));
+
l = gistfillbuffer(state->r, state->stack->page, state->itup, state->ituplen, off);
+ oldlsn = PageGetLSN(state->stack->page);
if ( !state->r->rd_istemp ) {
OffsetNumber noffs=0, offs[ MAXALIGN( sizeof(OffsetNumber) ) / sizeof(OffsetNumber) ];
XLogRecPtr recptr;
XLogRecData *rdata;
- if ( state->stack->todelete ) {
+ if ( !is_leaf ) {
+ /*only on inner page we should delete previous version */
offs[0] = state->stack->childoffnum;
noffs=1;
}
rdata = formUpdateRdata(state->r->rd_node, state->stack->blkno,
offs, noffs, false, state->itup, state->ituplen,
- &(state->key), state->path, state->pathlen);
+ &(state->key));
START_CRIT_SECTION();
@@ -383,11 +451,16 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) {
PageSetTLI(state->stack->page, ThisTimeLineID);
END_CRIT_SECTION();
- }
+ } else
+ PageSetLSN(state->stack->page, XLogRecPtrForTemp);
if ( state->stack->blkno == GIST_ROOT_BLKNO )
state->needInsertComplete=false;
- WriteBuffer(state->stack->buffer);
+ WriteNoReleaseBuffer(state->stack->buffer);
+
+ if (!is_leaf) /* small optimization: inform scan ablout deleting... */
+ gistadjscans(state->r, GISTOP_DEL, state->stack->blkno,
+ state->stack->childoffnum, PageGetLSN(state->stack->page), oldlsn );
if (state->ituplen > 1)
{ /* previous is_splitted==true */
@@ -409,17 +482,42 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) {
return is_splitted;
}
+/*
+ * returns stack of pages, all pages in stack are pinned, and
+ * leaf is X-locked
+ */
+
static void
gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
{
ItemId iid;
- IndexTuple oldtup;
- GISTInsertStack *ptr;
+ IndexTuple idxtuple;
+ GISTPageOpaque opaque;
+
+ /* walk down, We don't lock page for a long time, but so
+ we should be ready to recheck path in a bad case...
+ We remember, that page->lsn should never be invalid. */
+ while( true ) {
+
+ if ( XLogRecPtrIsInvalid( state->stack->lsn ) )
+ state->stack->buffer = ReadBuffer(state->r, state->stack->blkno);
+ LockBuffer( state->stack->buffer, GIST_SHARE );
- /* walk down */
- while( true ) {
- state->stack->buffer = gistReadBuffer(state->r, state->stack->blkno);
state->stack->page = (Page) BufferGetPage(state->stack->buffer);
+ opaque = GistPageGetOpaque(state->stack->page);
+
+ state->stack->lsn = PageGetLSN(state->stack->page);
+ Assert( state->r->rd_istemp || !XLogRecPtrIsInvalid( state->stack->lsn ) );
+
+ if ( state->stack->blkno != GIST_ROOT_BLKNO &&
+ XLByteLT( state->stack->parent->lsn, opaque->nsn) ) {
+ /* caused split non-root page is detected, go up to parent to choose best child */
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
+ ReleaseBuffer( state->stack->buffer );
+ state->stack = state->stack->parent;
+ continue;
+ }
+
if (!GistPageIsLeaf(state->stack->page))
{
@@ -432,42 +530,236 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
* split, or the key in this node needs to be adjusted for the
* newly inserted key below us.
*/
- GISTInsertStack *item=(GISTInsertStack*)palloc(sizeof(GISTInsertStack));
+ GISTInsertStack *item=(GISTInsertStack*)palloc0(sizeof(GISTInsertStack));
state->stack->childoffnum = gistchoose(state->r, state->stack->page, state->itup[0], giststate);
iid = PageGetItemId(state->stack->page, state->stack->childoffnum);
- oldtup = (IndexTuple) PageGetItem(state->stack->page, iid);
- item->blkno = ItemPointerGetBlockNumber(&(oldtup->t_tid));
+ idxtuple = (IndexTuple) PageGetItem(state->stack->page, iid);
+ item->blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid));
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
+
item->parent = state->stack;
- item->todelete = false;
+ item->child = NULL;
+ if ( state->stack )
+ state->stack->child = item;
state->stack = item;
- } else
+ } else {
+ /* be carefull, during unlock/lock page may be changed... */
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
+ LockBuffer( state->stack->buffer, GIST_EXCLUSIVE );
+ state->stack->page = (Page) BufferGetPage(state->stack->buffer);
+ opaque = GistPageGetOpaque(state->stack->page);
+
+ if ( state->stack->blkno == GIST_ROOT_BLKNO ) {
+ /* the only page can become inner instead of leaf is a root page,
+ so for root we should recheck it */
+ if ( !GistPageIsLeaf(state->stack->page) ) {
+ /* very rarely situation: during unlock/lock index
+ with number of pages = 1 was increased */
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
+ continue;
+ }
+ /* we don't need to check root split, because checking
+ leaf/inner is enough to recognize split for root */
+
+ } else if ( XLByteLT( state->stack->parent->lsn, opaque->nsn) ) {
+ /* detecting split during unlock/lock, so we should
+ find better child on parent*/
+
+ /* forget buffer */
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
+ ReleaseBuffer( state->stack->buffer );
+
+ state->stack = state->stack->parent;
+ continue;
+ }
+
+ state->stack->lsn = PageGetLSN( state->stack->page );
+
+ /* ok we found a leaf page and it X-locked */
break;
+ }
}
- /* now state->stack->(page, buffer and blkno) points to leaf page, so insert */
+ /* now state->stack->(page, buffer and blkno) points to leaf page */
+}
- /* form state->path to work xlog */
- ptr = state->stack;
- state->pathlen=1;
- while( ptr ) {
- state->pathlen++;
- ptr=ptr->parent;
- }
- state->path=(BlockNumber*)palloc(MAXALIGN(sizeof(BlockNumber)*state->pathlen));
- ptr = state->stack;
- state->pathlen=0;
- while( ptr ) {
- state->path[ state->pathlen ] = ptr->blkno;
- state->pathlen++;
- ptr=ptr->parent;
+/*
+ * Should have the same interface as XLogReadBuffer
+ */
+static Buffer
+gistReadAndLockBuffer( bool unused, Relation r, BlockNumber blkno ) {
+ Buffer buffer = ReadBuffer( r, blkno );
+ LockBuffer( buffer, GIST_SHARE );
+ return buffer;
+}
+
+/*
+ * Traverse the tree to find path from root page,
+ * to prevent deadlocks, it should lock only one page simultaneously.
+ * Function uses in recovery and usial mode, so should work with different
+ * read functions (gistReadAndLockBuffer and XLogReadBuffer)
+ * returns from the begining of closest parent;
+ */
+GISTInsertStack*
+gistFindPath( Relation r, BlockNumber child, Buffer (*myReadBuffer)(bool, Relation, BlockNumber) ) {
+ Page page;
+ Buffer buffer;
+ OffsetNumber i, maxoff;
+ ItemId iid;
+ IndexTuple idxtuple;
+ GISTInsertStack *top, *tail, *ptr;
+ BlockNumber blkno;
+
+ top = tail = (GISTInsertStack*)palloc0( sizeof(GISTInsertStack) );
+ top->blkno = GIST_ROOT_BLKNO;
+
+ while( top && top->blkno != child ) {
+ buffer = myReadBuffer(false, r, top->blkno); /* buffer locked */
+ page = (Page)BufferGetPage( buffer );
+ Assert( !GistPageIsLeaf(page) );
+
+ top->lsn = PageGetLSN(page);
+
+ if ( top->parent && XLByteLT( top->parent->lsn, GistPageGetOpaque(page)->nsn) &&
+ GistPageGetOpaque(page)->rightlink != InvalidBlockNumber /* sanity check */) {
+ /* page splited while we thinking of... */
+ ptr = (GISTInsertStack*)palloc0( sizeof(GISTInsertStack) );
+ ptr->blkno = GistPageGetOpaque(page)->rightlink;
+ ptr->childoffnum = InvalidOffsetNumber;
+ ptr->parent = top;
+ ptr->next = NULL;
+ tail->next = ptr;
+ tail = ptr;
+ }
+
+ maxoff = PageGetMaxOffsetNumber(page);
+
+ for(i = FirstOffsetNumber; i<= maxoff; i = OffsetNumberNext(i)) {
+ iid = PageGetItemId(page, i);
+ idxtuple = (IndexTuple) PageGetItem(page, iid);
+ blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid));
+ if ( blkno == child ) {
+ OffsetNumber poff = InvalidOffsetNumber;
+
+ /* make childs links */
+ ptr = top;
+ while( ptr->parent ) {
+ /* set child link */
+ ptr->parent->child = ptr;
+ /* move childoffnum.. */
+ if ( ptr == top ) {
+ /*first iteration*/
+ poff = ptr->parent->childoffnum;
+ ptr->parent->childoffnum = ptr->childoffnum;
+ } else {
+ OffsetNumber tmp = ptr->parent->childoffnum;
+ ptr->parent->childoffnum = poff;
+ poff = tmp;
+ }
+ ptr = ptr->parent;
+ }
+ top->childoffnum = i;
+ LockBuffer( buffer, GIST_UNLOCK );
+ ReleaseBuffer( buffer );
+ return top;
+ } else if ( GistPageGetOpaque(page)->level> 0 ) {
+ /* Install next inner page to the end of stack */
+ ptr = (GISTInsertStack*)palloc0( sizeof(GISTInsertStack) );
+ ptr->blkno = blkno;
+ ptr->childoffnum = i; /* set offsetnumber of child to child !!! */
+ ptr->parent = top;
+ ptr->next = NULL;
+ tail->next = ptr;
+ tail = ptr;
+ }
+ }
+
+ LockBuffer( buffer, GIST_UNLOCK );
+ ReleaseBuffer( buffer );
+ top = top->next;
}
- state->pathlen--;
- state->path++;
+
+ return NULL;
}
+/*
+ * Returns X-locked parent of stack page
+ */
+
+static void
+gistFindCorrectParent( Relation r, GISTInsertStack *child ) {
+ GISTInsertStack *parent = child->parent;
+
+ LockBuffer( parent->buffer, GIST_EXCLUSIVE );
+ parent->page = (Page)BufferGetPage( parent->buffer );
+
+
+ /* here we don't need to distinguish between split and page update */
+ if ( parent->childoffnum == InvalidOffsetNumber || !XLByteEQ( parent->lsn, PageGetLSN(parent->page) ) ) {
+ /* parent is changed, look child in right links until found */
+ OffsetNumber i, maxoff;
+ ItemId iid;
+ IndexTuple idxtuple;
+ GISTInsertStack *ptr;
+
+ while(true) {
+ maxoff = PageGetMaxOffsetNumber(parent->page);
+ for(i = FirstOffsetNumber; i<= maxoff; i = OffsetNumberNext(i)) {
+ iid = PageGetItemId(parent->page, i);
+ idxtuple = (IndexTuple) PageGetItem(parent->page, iid);
+ if ( ItemPointerGetBlockNumber(&(idxtuple->t_tid)) == child->blkno ) {
+ /* yes!!, found */
+ parent->childoffnum = i;
+ return;
+ }
+ }
+
+ parent->blkno = GistPageGetOpaque( parent->page )->rightlink;
+ LockBuffer( parent->buffer, GIST_UNLOCK );
+ ReleaseBuffer( parent->buffer );
+ if ( parent->blkno == InvalidBlockNumber )
+ /* end of chain and still didn't found parent,
+ It's very-very rare situation when root splited */
+ break;
+ parent->buffer = ReadBuffer( r, parent->blkno );
+ LockBuffer( parent->buffer, GIST_EXCLUSIVE );
+ parent->page = (Page)BufferGetPage( parent->buffer );
+ }
+
+ /* awful!!, we need search tree to find parent ... ,
+ but before we should release all old parent */
+
+ ptr = child->parent->parent; /* child->parent already released above */
+ while(ptr) {
+ ReleaseBuffer( ptr->buffer );
+ ptr = ptr->parent;
+ }
+
+ /* ok, find new path */
+ ptr = parent = gistFindPath(r, child->blkno, gistReadAndLockBuffer);
+ Assert( ptr!=NULL );
+
+ /* read all buffers as supposed in caller */
+ while( ptr ) {
+ ptr->buffer = ReadBuffer( r, ptr->blkno );
+ ptr->page = (Page)BufferGetPage( ptr->buffer );
+ ptr = ptr->parent;
+ }
+
+ /* install new chain of parents to stack */
+ child->parent = parent;
+ parent->child = child;
+
+ /* make recursive call to normal processing */
+ gistFindCorrectParent( r, child );
+ }
+
+ return;
+}
+
void
gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) {
int is_splitted;
@@ -482,19 +774,25 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) {
* then itup contains additional for adjustment of current key
*/
+ if ( state->stack->parent ) {
+ /* X-lock parent page before proceed child,
+ gistFindCorrectParent should find and lock it */
+ gistFindCorrectParent( state->r, state->stack );
+ }
is_splitted = gistplacetopage(state, giststate);
- /* pop page from stack */
+ /* parent locked above, so release child buffer */
+ LockBuffer(state->stack->buffer, GIST_UNLOCK );
+ ReleaseBuffer( state->stack->buffer );
+
+ /* pop parent page from stack */
state->stack = state->stack->parent;
- state->pathlen--;
- state->path++;
/* stack is void */
if ( ! state->stack )
break;
-
- /* child did not split */
+ /* child did not split, so we can check is it needed to update parent tuple */
if (!is_splitted)
{
/* parent's tuple */
@@ -502,34 +800,16 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) {
oldtup = (IndexTuple) PageGetItem(state->stack->page, iid);
newtup = gistgetadjusted(state->r, oldtup, state->itup[0], giststate);
- if (!newtup) /* not need to update key */
+ if (!newtup) { /* not need to update key */
+ LockBuffer( state->stack->buffer, GIST_UNLOCK );
break;
+ }
state->itup[0] = newtup;
- }
-
- /*
- * This node's key has been modified, either because a child
- * split occurred or because we needed to adjust our key for
- * an insert in a child node. Therefore, remove the old
- * version of this node's key.
- */
-
- gistadjscans(state->r, GISTOP_DEL, state->stack->blkno, state->stack->childoffnum);
- PageIndexTupleDelete(state->stack->page, state->stack->childoffnum);
- if ( !state->r->rd_istemp )
- state->stack->todelete = true;
-
- /*
- * if child was splitted, new key for child will be inserted in
- * the end list of child, so we must say to any scans that page is
- * changed beginning from 'child' offset
- */
- if (is_splitted)
- gistadjscans(state->r, GISTOP_SPLIT, state->stack->blkno, state->stack->childoffnum);
+ }
} /* while */
- /* release all buffers */
+ /* release all parent buffers */
while( state->stack ) {
ReleaseBuffer(state->stack->buffer);
state->stack = state->stack->parent;
@@ -577,9 +857,11 @@ gistSplit(Relation r,
OffsetNumber *realoffset;
IndexTuple *cleaneditup = itup;
int lencleaneditup = *len;
+ int level;
p = (Page) BufferGetPage(buffer);
- opaque = (GISTPageOpaque) PageGetSpecialPointer(p);
+ opaque = GistPageGetOpaque(p);
+ level = opaque->level;
/*
* The root of the tree is the first block in the relation. If we're
@@ -588,23 +870,25 @@ gistSplit(Relation r,
*/
if (BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO)
{
- leftbuf = gistReadBuffer(r, P_NEW);
+ leftbuf = gistNewBuffer(r);
GISTInitBuffer(leftbuf, opaque->flags&F_LEAF);
lbknum = BufferGetBlockNumber(leftbuf);
left = (Page) BufferGetPage(leftbuf);
+ GistPageGetOpaque(left)->level = level;
}
else
{
leftbuf = buffer;
- IncrBufferRefCount(buffer);
+ /* IncrBufferRefCount(buffer); */
lbknum = BufferGetBlockNumber(buffer);
left = (Page) PageGetTempPage(p, sizeof(GISTPageOpaqueData));
}
- rightbuf = gistReadBuffer(r, P_NEW);
+ rightbuf = gistNewBuffer(r);
GISTInitBuffer(rightbuf, opaque->flags&F_LEAF);
rbknum = BufferGetBlockNumber(rightbuf);
right = (Page) BufferGetPage(rightbuf);
+ GistPageGetOpaque(right)->level = level;
/* generate the item array */
realoffset = palloc((*len + 1) * sizeof(OffsetNumber));
@@ -711,7 +995,7 @@ gistSplit(Relation r,
{
nlen = v.spl_nright;
newtup = gistSplit(r, rightbuf, rvectup, &nlen, dist, giststate);
- ReleaseBuffer(rightbuf);
+ /* ReleaseBuffer(rightbuf); */
}
else
{
@@ -745,7 +1029,7 @@ gistSplit(Relation r,
IndexTuple *lntup;
lntup = gistSplit(r, leftbuf, lvectup, &llen, dist, giststate);
- ReleaseBuffer(leftbuf);
+ /* ReleaseBuffer(leftbuf); */
newtup = gistjoinvector(newtup, &nlen, lntup, llen);
}
@@ -785,14 +1069,16 @@ gistSplit(Relation r,
}
void
-gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key)
+gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer key)
{
- Buffer buffer;
Page page;
+ int level;
- buffer = gistReadBuffer(r, GIST_ROOT_BLKNO);
- GISTInitBuffer(buffer, 0);
+ Assert( BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO );
page = BufferGetPage(buffer);
+ level = GistPageGetOpaque(page)->level;
+ GISTInitBuffer(buffer, 0);
+ GistPageGetOpaque(page)->level = level+1;
gistfillbuffer(r, page, itup, len, FirstOffsetNumber);
if ( !r->rd_istemp ) {
@@ -800,8 +1086,7 @@ gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key)
XLogRecData *rdata;
rdata = formUpdateRdata(r->rd_node, GIST_ROOT_BLKNO,
- NULL, 0, false, itup, len,
- key, NULL, 0);
+ NULL, 0, false, itup, len, key);
START_CRIT_SECTION();
@@ -810,8 +1095,8 @@ gistnewroot(Relation r, IndexTuple *itup, int len, ItemPointer key)
PageSetTLI(page, ThisTimeLineID);
END_CRIT_SECTION();
- }
- WriteBuffer(buffer);
+ } else
+ PageSetLSN(page, XLogRecPtrForTemp);
}
void