diff options
author | Bruce Momjian <bruce@momjian.us> | 2005-09-22 20:44:36 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2005-09-22 20:44:36 +0000 |
commit | b3364fc81b78538006da3b3ad5680530d2af8c47 (patch) | |
tree | e73b69951621d2d2417d05969499218298cfa68b /src/backend/access/gist/gist.c | |
parent | 08817bdb76d2a137bb7a4d1fe7551746d9045c8e (diff) | |
download | postgresql-b3364fc81b78538006da3b3ad5680530d2af8c47.tar.gz postgresql-b3364fc81b78538006da3b3ad5680530d2af8c47.zip |
pgindent new GIST index code, per request from Tom.
Diffstat (limited to 'src/backend/access/gist/gist.c')
-rw-r--r-- | src/backend/access/gist/gist.c | 820 |
1 files changed, 468 insertions, 352 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 5ce3fceba6b..89f59ebc279 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.125 2005/06/30 17:52:13 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.126 2005/09/22 20:44:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,7 @@ #include "miscadmin.h" #include "utils/memutils.h" -const XLogRecPtr XLogRecPtrForTemp = { 1, 1 }; +const XLogRecPtr XLogRecPtrForTemp = {1, 1}; /* Working state for gistbuild and its callback */ typedef struct @@ -46,7 +46,7 @@ static void gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *GISTstate); static void gistfindleaf(GISTInsertState *state, - GISTSTATE *giststate); + GISTSTATE *giststate); #define ROTATEDIST(d) do { \ @@ -55,7 +55,7 @@ static void gistfindleaf(GISTInsertState *state, tmp->next = (d); \ (d)=tmp; \ } while(0) - + /* * Create and return a temporary memory context for use by GiST. We @@ -65,15 +65,15 @@ static void gistfindleaf(GISTInsertState *state, * GiST code itself, to avoid the need to do some awkward manual * memory management. */ -MemoryContext -createTempGistContext(void) -{ - return AllocSetContextCreate(CurrentMemoryContext, - "GiST temporary context", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); -} +MemoryContext +createTempGistContext(void) +{ + return AllocSetContextCreate(CurrentMemoryContext, + "GiST temporary context", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); +} /* * Routine to build an index. Basically calls insert over and over. @@ -92,8 +92,8 @@ gistbuild(PG_FUNCTION_ARGS) Buffer buffer; /* - * We expect to be called exactly once for any index relation. If - * that's not the case, big trouble's what we have. + * We expect to be called exactly once for any index relation. If that's + * not the case, big trouble's what we have. */ if (RelationGetNumberOfBlocks(index) != 0) elog(ERROR, "index \"%s\" already contains data", @@ -105,15 +105,16 @@ gistbuild(PG_FUNCTION_ARGS) /* initialize the root page */ buffer = gistNewBuffer(index); GISTInitBuffer(buffer, F_LEAF); - if ( !index->rd_istemp ) { - XLogRecPtr recptr; - XLogRecData rdata; - Page page; + if (!index->rd_istemp) + { + XLogRecPtr recptr; + XLogRecData rdata; + Page page; - rdata.buffer = InvalidBuffer; - rdata.data = (char*)&(index->rd_node); - rdata.len = sizeof(RelFileNode); - rdata.next = NULL; + rdata.buffer = InvalidBuffer; + rdata.data = (char *) &(index->rd_node); + rdata.len = sizeof(RelFileNode); + rdata.next = NULL; page = BufferGetPage(buffer); @@ -124,7 +125,8 @@ gistbuild(PG_FUNCTION_ARGS) PageSetTLI(page, ThisTimeLineID); END_CRIT_SECTION(); - } else + } + else PageSetLSN(BufferGetPage(buffer), XLogRecPtrForTemp); LockBuffer(buffer, GIST_UNLOCK); WriteBuffer(buffer); @@ -132,9 +134,10 @@ gistbuild(PG_FUNCTION_ARGS) /* build the index */ buildstate.numindexattrs = indexInfo->ii_NumIndexAttrs; buildstate.indtuples = 0; + /* - * create a temporary memory context that is reset once for each - * tuple inserted into the index + * create a temporary memory context that is reset once for each tuple + * inserted into the index */ buildstate.tmpCtx = createTempGistContext(); @@ -185,7 +188,7 @@ gistbuildCallback(Relation index, { gistcentryinit(&buildstate->giststate, i, &tmpcentry, values[i], NULL, NULL, (OffsetNumber) 0, - -1 /* size is currently bogus */, TRUE, FALSE); + -1 /* size is currently bogus */ , TRUE, FALSE); values[i] = tmpcentry.key; } } @@ -195,11 +198,11 @@ gistbuildCallback(Relation index, itup->t_tid = htup->t_self; /* - * Since we already have the index relation locked, we call - * gistdoinsert directly. Normal access method calls dispatch through - * gistinsert, which locks the relation for write. This is the right - * thing to do if you're inserting single tups, but not when you're - * initializing the whole index at once. + * Since we already have the index relation locked, we call gistdoinsert + * directly. Normal access method calls dispatch through gistinsert, + * which locks the relation for write. This is the right thing to do if + * you're inserting single tups, but not when you're initializing the + * whole index at once. */ gistdoinsert(index, itup, &buildstate->giststate); @@ -221,6 +224,7 @@ gistinsert(PG_FUNCTION_ARGS) Datum *values = (Datum *) PG_GETARG_POINTER(1); bool *isnull = (bool *) PG_GETARG_POINTER(2); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); + #ifdef NOT_USED Relation heapRel = (Relation) PG_GETARG_POINTER(4); bool checkUnique = PG_GETARG_BOOL(5); @@ -250,7 +254,7 @@ gistinsert(PG_FUNCTION_ARGS) { gistcentryinit(&giststate, i, &tmpentry, values[i], NULL, NULL, (OffsetNumber) 0, - -1 /* size is currently bogus */, TRUE, FALSE); + -1 /* size is currently bogus */ , TRUE, FALSE); values[i] = tmpentry.key; } } @@ -276,148 +280,167 @@ gistinsert(PG_FUNCTION_ARGS) static void gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate) { - GISTInsertState state; + GISTInsertState state; memset(&state, 0, sizeof(GISTInsertState)); state.itup = (IndexTuple *) palloc(sizeof(IndexTuple)); state.itup[0] = (IndexTuple) palloc(IndexTupleSize(itup)); memcpy(state.itup[0], itup, IndexTupleSize(itup)); - state.ituplen=1; + state.ituplen = 1; state.r = r; state.key = itup->t_tid; - state.needInsertComplete = true; + state.needInsertComplete = true; - state.stack = (GISTInsertStack*)palloc0(sizeof(GISTInsertStack)); - state.stack->blkno=GIST_ROOT_BLKNO; + state.stack = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack)); + state.stack->blkno = GIST_ROOT_BLKNO; gistfindleaf(&state, giststate); gistmakedeal(&state, giststate); } static bool -gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) { - bool is_splitted = false; - bool is_leaf = (GistPageIsLeaf(state->stack->page)) ? true : false; +gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) +{ + bool is_splitted = false; + bool is_leaf = (GistPageIsLeaf(state->stack->page)) ? true : false; - if ( !is_leaf ) + 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. + * 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 */ IndexTuple *itvec, *newitup; - int tlen,olen; - SplitedPageLayout *dist=NULL, *ptr; + int tlen, + olen; + SplitedPageLayout *dist = NULL, + *ptr; is_splitted = true; itvec = gistextractbuffer(state->stack->buffer, &tlen); - olen=tlen; + olen = tlen; itvec = gistjoinvector(itvec, &tlen, state->itup, state->ituplen); newitup = gistSplit(state->r, state->stack->buffer, itvec, &tlen, &dist, giststate); - if ( !state->r->rd_istemp ) { + if (!state->r->rd_istemp) + { XLogRecPtr recptr; - XLogRecData *rdata; - + XLogRecData *rdata; + rdata = formSplitRdata(state->r->rd_node, state->stack->blkno, - &(state->key), dist); + &(state->key), dist); START_CRIT_SECTION(); recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT, rdata); ptr = dist; - while(ptr) { + while (ptr) + { PageSetLSN(BufferGetPage(ptr->buffer), recptr); PageSetTLI(BufferGetPage(ptr->buffer), ThisTimeLineID); - ptr=ptr->next; + ptr = ptr->next; } END_CRIT_SECTION(); - } else { + } + else + { ptr = dist; - while(ptr) { + while (ptr) + { PageSetLSN(BufferGetPage(ptr->buffer), XLogRecPtrForTemp); - ptr=ptr->next; + ptr = ptr->next; } } state->itup = newitup; - state->ituplen = tlen; /* now tlen >= 2 */ + state->ituplen = tlen; /* now tlen >= 2 */ - if ( state->stack->blkno == GIST_ROOT_BLKNO ) { + if (state->stack->blkno == GIST_ROOT_BLKNO) + { gistnewroot(state->r, state->stack->buffer, state->itup, state->ituplen, &(state->key)); - state->needInsertComplete=false; + state->needInsertComplete = false; ptr = dist; - while(ptr) { - Page page = (Page)BufferGetPage(ptr->buffer); - GistPageGetOpaque(page)->rightlink = ( ptr->next ) ? + while (ptr) + { + Page page = (Page) BufferGetPage(ptr->buffer); + + GistPageGetOpaque(page)->rightlink = (ptr->next) ? ptr->next->block.blkno : InvalidBlockNumber; GistPageGetOpaque(page)->nsn = PageGetLSN(page); - LockBuffer( ptr->buffer, GIST_UNLOCK ); + LockBuffer(ptr->buffer, GIST_UNLOCK); WriteBuffer(ptr->buffer); - ptr=ptr->next; + ptr = ptr->next; } - } else { - Page page; - BlockNumber rightrightlink = InvalidBlockNumber; - SplitedPageLayout *ourpage=NULL; - GistNSN oldnsn; + } + 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 ) { + if (dist->block.blkno != state->stack->blkno) + { ptr = dist; - while(ptr->next) { - if ( ptr->next->block.blkno == state->stack->blkno ) { + 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; + ptr = ptr->next; } - Assert( ourpage != NULL ); - } else + Assert(ourpage != NULL); + } + else ourpage = dist; - + /* now gets all needed data, and sets nsn's */ - page = (Page)BufferGetPage(ourpage->buffer); + 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 */ + /* + * 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 ) ? + 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 ) ? + GistPageGetOpaque(page)->nsn = (ptr->next) ? opaque->nsn : oldnsn; LockBuffer(ptr->buffer, GIST_UNLOCK); WriteBuffer(ptr->buffer); - ptr=ptr->next; + ptr = ptr->next; } } - WriteNoReleaseBuffer( state->stack->buffer ); + WriteNoReleaseBuffer(state->stack->buffer); } else { @@ -427,20 +450,23 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) { gistfillbuffer(state->r, state->stack->page, state->itup, state->ituplen, InvalidOffsetNumber); oldlsn = PageGetLSN(state->stack->page); - if ( !state->r->rd_istemp ) { - OffsetNumber noffs=0, offs[ MAXALIGN( sizeof(OffsetNumber) ) / sizeof(OffsetNumber) ]; + if (!state->r->rd_istemp) + { + OffsetNumber noffs = 0, + offs[MAXALIGN(sizeof(OffsetNumber)) / sizeof(OffsetNumber)]; XLogRecPtr recptr; - XLogRecData *rdata; - - if ( !is_leaf ) { - /*only on inner page we should delete previous version */ + XLogRecData *rdata; + + if (!is_leaf) + { + /* only on inner page we should delete previous version */ offs[0] = state->stack->childoffnum; - noffs=1; + noffs = 1; } - + rdata = formUpdateRdata(state->r->rd_node, state->stack->blkno, - offs, noffs, false, state->itup, state->ituplen, - &(state->key)); + offs, noffs, false, state->itup, state->ituplen, + &(state->key)); START_CRIT_SECTION(); @@ -449,69 +475,84 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) { PageSetTLI(state->stack->page, ThisTimeLineID); END_CRIT_SECTION(); - } else + } + else PageSetLSN(state->stack->page, XLogRecPtrForTemp); - if ( state->stack->blkno == GIST_ROOT_BLKNO ) - state->needInsertComplete=false; + if (state->stack->blkno == GIST_ROOT_BLKNO) + state->needInsertComplete = false; 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 (!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 */ + /* * child was splited, so we must form union for insertion in * parent */ IndexTuple newtup = gistunion(state->r, state->itup, state->ituplen, giststate); + ItemPointerSetBlockNumber(&(newtup->t_tid), state->stack->blkno); state->itup[0] = newtup; state->ituplen = 1; - } else if (is_leaf) { - /* itup[0] store key to adjust parent, we set it to valid - to correct check by GistTupleIsInvalid macro in gistgetadjusted() */ + } + else if (is_leaf) + { + /* + * itup[0] store key to adjust parent, we set it to valid to + * correct check by GistTupleIsInvalid macro in gistgetadjusted() + */ ItemPointerSetBlockNumber(&(state->itup[0]->t_tid), state->stack->blkno); - GistTupleSetValid( state->itup[0] ); + GistTupleSetValid(state->itup[0]); } } return is_splitted; } /* - * returns stack of pages, all pages in stack are pinned, and + * 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 idxtuple; - GISTPageOpaque opaque; + 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 ) { + /* + * 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 ) ) + if (XLogRecPtrIsInvalid(state->stack->lsn)) state->stack->buffer = ReadBuffer(state->r, state->stack->blkno); - LockBuffer( state->stack->buffer, GIST_SHARE ); + LockBuffer(state->stack->buffer, GIST_SHARE); 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 ) ); + 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 ); + 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; } @@ -519,62 +560,76 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate) if (!GistPageIsLeaf(state->stack->page)) { - /* - * This is an internal page, so continue to walk down the - * tree. We find the child node that has the minimum insertion - * penalty and recursively invoke ourselves to modify that - * node. Once the recursive call returns, we may need to - * adjust the parent node for two reasons: the child node - * split, or the key in this node needs to be adjusted for the - * newly inserted key below us. - */ - GISTInsertStack *item=(GISTInsertStack*)palloc0(sizeof(GISTInsertStack)); - + /* + * This is an internal page, so continue to walk down the tree. We + * find the child node that has the minimum insertion penalty and + * recursively invoke ourselves to modify that node. Once the + * recursive call returns, we may need to adjust the parent node + * for two reasons: the child node split, or the key in this node + * needs to be adjusted for the newly inserted key below us. + */ + 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); idxtuple = (IndexTuple) PageGetItem(state->stack->page, iid); item->blkno = ItemPointerGetBlockNumber(&(idxtuple->t_tid)); - LockBuffer( state->stack->buffer, GIST_UNLOCK ); + LockBuffer(state->stack->buffer, GIST_UNLOCK); item->parent = state->stack; item->child = NULL; - if ( state->stack ) + 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 ); + 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 ); + 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*/ + } + + /* + * 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 ); + LockBuffer(state->stack->buffer, GIST_UNLOCK); + ReleaseBuffer(state->stack->buffer); state->stack = state->stack->parent; - continue; + continue; } - state->stack->lsn = PageGetLSN( state->stack->page ); - + state->stack->lsn = PageGetLSN(state->stack->page); + /* ok we found a leaf page and it X-locked */ break; } @@ -587,10 +642,12 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate) * Should have the same interface as XLogReadBuffer */ static Buffer -gistReadAndLockBuffer( Relation r, BlockNumber blkno ) { - Buffer buffer = ReadBuffer( r, blkno ); - LockBuffer( buffer, GIST_SHARE ); - return buffer; +gistReadAndLockBuffer(Relation r, BlockNumber blkno) +{ + Buffer buffer = ReadBuffer(r, blkno); + + LockBuffer(buffer, GIST_SHARE); + return buffer; } /* @@ -598,38 +655,45 @@ gistReadAndLockBuffer( Relation r, BlockNumber blkno ) { * 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; + * returns from the begining of closest parent; */ -GISTInsertStack* -gistFindPath( Relation r, BlockNumber child, Buffer (*myReadBuffer)(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) ); +GISTInsertStack * +gistFindPath(Relation r, BlockNumber child, Buffer (*myReadBuffer) (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(r, top->blkno); /* buffer locked */ - page = (Page)BufferGetPage( buffer ); + while (top && top->blkno != child) + { + buffer = myReadBuffer(r, top->blkno); /* buffer locked */ + page = (Page) BufferGetPage(buffer); - if ( GistPageIsLeaf(page) ) { + if (GistPageIsLeaf(page)) + { /* we can safety go away, follows only leaf pages */ - LockBuffer( buffer, GIST_UNLOCK ); - ReleaseBuffer( buffer ); + LockBuffer(buffer, GIST_UNLOCK); + ReleaseBuffer(buffer); return NULL; } - top->lsn = PageGetLSN(page); + top->lsn = PageGetLSN(page); - if ( top->parent && XLByteLT( top->parent->lsn, GistPageGetOpaque(page)->nsn) && - GistPageGetOpaque(page)->rightlink != InvalidBlockNumber /* sanity check */) { + 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 = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack)); ptr->blkno = GistPageGetOpaque(page)->rightlink; ptr->childoffnum = InvalidOffsetNumber; ptr->parent = top; @@ -637,119 +701,143 @@ gistFindPath( Relation r, BlockNumber child, Buffer (*myReadBuffer)(Relation, B tail->next = ptr; tail = ptr; } - + maxoff = PageGetMaxOffsetNumber(page); - for(i = FirstOffsetNumber; i<= maxoff; i = OffsetNumberNext(i)) { + 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 ) { + if (blkno == child) + { OffsetNumber poff = InvalidOffsetNumber; - + /* make childs links */ ptr = top; - while( ptr->parent ) { + while (ptr->parent) + { /* set child link */ ptr->parent->child = ptr; /* move childoffnum.. */ - if ( ptr == top ) { - /*first iteration*/ + if (ptr == top) + { + /* first iteration */ poff = ptr->parent->childoffnum; ptr->parent->childoffnum = ptr->childoffnum; - } else { + } + else + { OffsetNumber tmp = ptr->parent->childoffnum; + ptr->parent->childoffnum = poff; poff = tmp; } ptr = ptr->parent; } top->childoffnum = i; - LockBuffer( buffer, GIST_UNLOCK ); - ReleaseBuffer( buffer ); + LockBuffer(buffer, GIST_UNLOCK); + ReleaseBuffer(buffer); return top; - } else { + } + else + { /* Install next inner page to the end of stack */ - ptr = (GISTInsertStack*)palloc0( sizeof(GISTInsertStack) ); + ptr = (GISTInsertStack *) palloc0(sizeof(GISTInsertStack)); ptr->blkno = blkno; - ptr->childoffnum = i; /* set offsetnumber of child to child !!! */ + 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 ); + + LockBuffer(buffer, GIST_UNLOCK); + ReleaseBuffer(buffer); top = top->next; } - return NULL; + 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 ); +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) ) ) { + 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) { + OffsetNumber i, + maxoff; + ItemId iid; + IndexTuple idxtuple; + GISTInsertStack *ptr; + + while (true) + { maxoff = PageGetMaxOffsetNumber(parent->page); - for(i = FirstOffsetNumber; i<= maxoff; i = OffsetNumberNext(i)) { + 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 ) { + 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 */ + + 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 ); - } + 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 */ + /* + * 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 = 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 ); + Assert(ptr != NULL); - /* read all buffers as supposed in caller */ - while( ptr ) { - ptr->buffer = ReadBuffer( r, ptr->blkno ); - ptr->page = (Page)BufferGetPage( ptr->buffer ); + /* read all buffers as supposed in caller */ + while (ptr) + { + ptr->buffer = ReadBuffer(r, ptr->blkno); + ptr->page = (Page) BufferGetPage(ptr->buffer); ptr = ptr->parent; } @@ -758,78 +846,90 @@ gistFindCorrectParent( Relation r, GISTInsertStack *child ) { parent->child = child; /* make recursive call to normal processing */ - gistFindCorrectParent( r, child ); - } + gistFindCorrectParent(r, child); + } return; } void -gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) { +gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) +{ int is_splitted; ItemId iid; - IndexTuple oldtup, newtup; + IndexTuple oldtup, + newtup; /* walk up */ - while( true ) { - /* - * After this call: 1. if child page was splited, then itup - * contains keys for each page 2. if child page wasn't splited, - * 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 ); + while (true) + { + /* + * After this call: 1. if child page was splited, then itup contains + * keys for each page 2. if child page wasn't splited, 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); /* parent locked above, so release child buffer */ - LockBuffer(state->stack->buffer, GIST_UNLOCK ); - ReleaseBuffer( state->stack->buffer ); + LockBuffer(state->stack->buffer, GIST_UNLOCK); + ReleaseBuffer(state->stack->buffer); /* pop parent page from stack */ state->stack = state->stack->parent; - + /* stack is void */ - if ( ! state->stack ) + if (!state->stack) break; - /* child did not split, so we can check is it needed to update parent tuple */ + /* + * child did not split, so we can check is it needed to update parent + * tuple + */ if (!is_splitted) { /* parent's tuple */ iid = PageGetItemId(state->stack->page, state->stack->childoffnum); oldtup = (IndexTuple) PageGetItem(state->stack->page, iid); newtup = gistgetadjusted(state->r, oldtup, state->itup[0], giststate); - - if (!newtup) { /* not need to update key */ - LockBuffer( state->stack->buffer, GIST_UNLOCK ); + + if (!newtup) + { /* not need to update key */ + LockBuffer(state->stack->buffer, GIST_UNLOCK); break; } - state->itup[0] = newtup; - } - } /* while */ + state->itup[0] = newtup; + } + } /* while */ /* release all parent buffers */ - while( state->stack ) { + while (state->stack) + { ReleaseBuffer(state->stack->buffer); state->stack = state->stack->parent; } /* say to xlog that insert is completed */ - if ( state->needInsertComplete && !state->r->rd_istemp ) - gistxlogInsertCompletion(state->r->rd_node, &(state->key), 1); + if (state->needInsertComplete && !state->r->rd_istemp) + gistxlogInsertCompletion(state->r->rd_node, &(state->key), 1); } -static void -gistToRealOffset(OffsetNumber *arr, int len, OffsetNumber *reasloffset) { - int i; +static void +gistToRealOffset(OffsetNumber *arr, int len, OffsetNumber *reasloffset) +{ + int i; - for(i=0;i<len;i++) - arr[i] = reasloffset[ arr[i] ]; + for (i = 0; i < len; i++) + arr[i] = reasloffset[arr[i]]; } /* @@ -840,7 +940,7 @@ gistSplit(Relation r, Buffer buffer, IndexTuple *itup, /* contains compressed entry */ int *len, - SplitedPageLayout **dist, + SplitedPageLayout **dist, GISTSTATE *giststate) { Page p; @@ -856,24 +956,25 @@ gistSplit(Relation r, GISTPageOpaque opaque; GIST_SPLITVEC v; GistEntryVector *entryvec; - int i, fakeoffset, + int i, + fakeoffset, nlen; - OffsetNumber *realoffset; - IndexTuple *cleaneditup = itup; - int lencleaneditup = *len; + OffsetNumber *realoffset; + IndexTuple *cleaneditup = itup; + int lencleaneditup = *len; p = (Page) BufferGetPage(buffer); opaque = GistPageGetOpaque(p); /* * The root of the tree is the first block in the relation. If we're - * about to split the root, we need to do some hocus-pocus to enforce - * this guarantee. + * about to split the root, we need to do some hocus-pocus to enforce this + * guarantee. */ if (BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO) { leftbuf = gistNewBuffer(r); - GISTInitBuffer(leftbuf, opaque->flags&F_LEAF); + GISTInitBuffer(leftbuf, opaque->flags & F_LEAF); lbknum = BufferGetBlockNumber(leftbuf); left = (Page) BufferGetPage(leftbuf); } @@ -886,7 +987,7 @@ gistSplit(Relation r, } rightbuf = gistNewBuffer(r); - GISTInitBuffer(rightbuf, opaque->flags&F_LEAF); + GISTInitBuffer(rightbuf, opaque->flags & F_LEAF); rbknum = BufferGetBlockNumber(rightbuf); right = (Page) BufferGetPage(rightbuf); @@ -901,10 +1002,11 @@ gistSplit(Relation r, Datum datum; bool IsNull; - if (!GistPageIsLeaf(p) && GistTupleIsInvalid( itup[i - 1] )) { + if (!GistPageIsLeaf(p) && GistTupleIsInvalid(itup[i - 1])) + { entryvec->n--; /* remember position of invalid tuple */ - realoffset[ entryvec->n ] = i; + realoffset[entryvec->n] = i; continue; } @@ -913,54 +1015,62 @@ gistSplit(Relation r, datum, r, p, i, ATTSIZE(datum, giststate->tupdesc, 1, IsNull), FALSE, IsNull); - realoffset[ fakeoffset ] = i; + realoffset[fakeoffset] = i; fakeoffset++; } - /* - * if it was invalid tuple then we need special processing. If - * it's possible, we move all invalid tuples on right page. - * We should remember, that union with invalid tuples - * is a invalid tuple. - */ - if ( entryvec->n != *len + 1 ) { - lencleaneditup = entryvec->n-1; - cleaneditup = (IndexTuple*)palloc(lencleaneditup * sizeof(IndexTuple)); - for(i=1;i<entryvec->n;i++) - cleaneditup[i-1] = itup[ realoffset[ i ]-1 ]; - - if ( gistnospace( left, cleaneditup, lencleaneditup ) ) { - /* no space on left to put all good tuples, so picksplit */ + /* + * if it was invalid tuple then we need special processing. If it's + * possible, we move all invalid tuples on right page. We should remember, + * that union with invalid tuples is a invalid tuple. + */ + if (entryvec->n != *len + 1) + { + lencleaneditup = entryvec->n - 1; + cleaneditup = (IndexTuple *) palloc(lencleaneditup * sizeof(IndexTuple)); + for (i = 1; i < entryvec->n; i++) + cleaneditup[i - 1] = itup[realoffset[i] - 1]; + + if (gistnospace(left, cleaneditup, lencleaneditup)) + { + /* no space on left to put all good tuples, so picksplit */ gistUserPicksplit(r, entryvec, &v, cleaneditup, lencleaneditup, giststate); v.spl_leftvalid = true; v.spl_rightvalid = false; - gistToRealOffset( v.spl_left, v.spl_nleft, realoffset ); - gistToRealOffset( v.spl_right, v.spl_nright, realoffset ); - } else { - /* we can try to store all valid tuples on one page */ - v.spl_right = (OffsetNumber*)palloc( entryvec->n * sizeof(OffsetNumber) ); - v.spl_left = (OffsetNumber*)palloc( entryvec->n * sizeof(OffsetNumber) ); - - if ( lencleaneditup==0 ) { + gistToRealOffset(v.spl_left, v.spl_nleft, realoffset); + gistToRealOffset(v.spl_right, v.spl_nright, realoffset); + } + else + { + /* we can try to store all valid tuples on one page */ + v.spl_right = (OffsetNumber *) palloc(entryvec->n * sizeof(OffsetNumber)); + v.spl_left = (OffsetNumber *) palloc(entryvec->n * sizeof(OffsetNumber)); + + if (lencleaneditup == 0) + { /* all tuples are invalid, so moves half of its to right */ v.spl_leftvalid = v.spl_rightvalid = false; v.spl_nright = 0; v.spl_nleft = 0; - for(i=1;i<=*len;i++) - if ( i-1<*len/2 ) - v.spl_left[ v.spl_nleft++ ] = i; + for (i = 1; i <= *len; i++) + if (i - 1 < *len / 2) + v.spl_left[v.spl_nleft++] = i; else - v.spl_right[ v.spl_nright++ ] = i; - } else { - /* we will not call gistUserPicksplit, just put good - tuples on left and invalid on right */ + v.spl_right[v.spl_nright++] = i; + } + else + { + /* + * we will not call gistUserPicksplit, just put good tuples on + * left and invalid on right + */ v.spl_nleft = lencleaneditup; v.spl_nright = 0; - for(i=1;i<entryvec->n;i++) - v.spl_left[i-1] = i; - gistToRealOffset( v.spl_left, v.spl_nleft, realoffset ); - v.spl_lattr[0] = v.spl_ldatum = (Datum)0; - v.spl_rattr[0] = v.spl_rdatum = (Datum)0; + for (i = 1; i < entryvec->n; i++) + v.spl_left[i - 1] = i; + gistToRealOffset(v.spl_left, v.spl_nleft, realoffset); + v.spl_lattr[0] = v.spl_ldatum = (Datum) 0; + v.spl_rattr[0] = v.spl_rdatum = (Datum) 0; v.spl_lisnull[0] = true; v.spl_risnull[0] = true; gistunionsubkey(r, giststate, itup, &v, true); @@ -968,16 +1078,18 @@ gistSplit(Relation r, v.spl_rightvalid = false; } } - } else { - /* there is no invalid tuples, so usial processing */ + } + else + { + /* there is no invalid tuples, so usial processing */ gistUserPicksplit(r, entryvec, &v, itup, *len, giststate); v.spl_leftvalid = v.spl_rightvalid = true; } /* form left and right vector */ - lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (*len+1)); - rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (*len+1)); + lvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (*len + 1)); + rvectup = (IndexTuple *) palloc(sizeof(IndexTuple) * (*len + 1)); for (i = 0; i < v.spl_nleft; i++) lvectup[i] = itup[v.spl_left[i] - 1]; @@ -986,7 +1098,8 @@ gistSplit(Relation r, rvectup[i] = itup[v.spl_right[i] - 1]; /* place invalid tuples on right page if itsn't done yet */ - for (fakeoffset = entryvec->n; fakeoffset < *len+1 && lencleaneditup; fakeoffset++) { + for (fakeoffset = entryvec->n; fakeoffset < *len + 1 && lencleaneditup; fakeoffset++) + { rvectup[v.spl_nright++] = itup[realoffset[fakeoffset] - 1]; } @@ -999,26 +1112,27 @@ gistSplit(Relation r, } else { - char *ptr; + char *ptr; gistfillbuffer(r, right, rvectup, v.spl_nright, FirstOffsetNumber); /* XLOG stuff */ ROTATEDIST(*dist); (*dist)->block.blkno = BufferGetBlockNumber(rightbuf); (*dist)->block.num = v.spl_nright; - (*dist)->list = (IndexTupleData*)palloc( BLCKSZ ); - ptr = (char*) ( (*dist)->list ); - for(i=0;i<v.spl_nright;i++) { - memcpy( ptr, rvectup[i], IndexTupleSize( rvectup[i] ) ); - ptr += IndexTupleSize( rvectup[i] ); + (*dist)->list = (IndexTupleData *) palloc(BLCKSZ); + ptr = (char *) ((*dist)->list); + for (i = 0; i < v.spl_nright; i++) + { + memcpy(ptr, rvectup[i], IndexTupleSize(rvectup[i])); + ptr += IndexTupleSize(rvectup[i]); } - (*dist)->lenlist = ptr - ( (char*) ( (*dist)->list ) ); + (*dist)->lenlist = ptr - ((char *) ((*dist)->list)); (*dist)->buffer = rightbuf; - + nlen = 1; newtup = (IndexTuple *) palloc(sizeof(IndexTuple) * 1); - newtup[0] = ( v.spl_rightvalid ) ? gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull) - : gist_form_invalid_tuple( rbknum ); + newtup[0] = (v.spl_rightvalid) ? gistFormTuple(giststate, r, v.spl_rattr, v.spl_rattrsize, v.spl_risnull) + : gist_form_invalid_tuple(rbknum); ItemPointerSetBlockNumber(&(newtup[0]->t_tid), rbknum); } @@ -1034,34 +1148,35 @@ gistSplit(Relation r, } else { - char *ptr; + char *ptr; gistfillbuffer(r, left, lvectup, v.spl_nleft, FirstOffsetNumber); /* XLOG stuff */ ROTATEDIST(*dist); (*dist)->block.blkno = BufferGetBlockNumber(leftbuf); (*dist)->block.num = v.spl_nleft; - (*dist)->list = (IndexTupleData*)palloc( BLCKSZ ); - ptr = (char*) ( (*dist)->list ); - for(i=0;i<v.spl_nleft;i++) { - memcpy( ptr, lvectup[i], IndexTupleSize( lvectup[i] ) ); - ptr += IndexTupleSize( lvectup[i] ); + (*dist)->list = (IndexTupleData *) palloc(BLCKSZ); + ptr = (char *) ((*dist)->list); + for (i = 0; i < v.spl_nleft; i++) + { + memcpy(ptr, lvectup[i], IndexTupleSize(lvectup[i])); + ptr += IndexTupleSize(lvectup[i]); } - (*dist)->lenlist = ptr - ( (char*) ( (*dist)->list ) ); + (*dist)->lenlist = ptr - ((char *) ((*dist)->list)); (*dist)->buffer = leftbuf; - + if (BufferGetBlockNumber(buffer) != GIST_ROOT_BLKNO) PageRestoreTempPage(left, p); nlen += 1; newtup = (IndexTuple *) repalloc(newtup, sizeof(IndexTuple) * nlen); - newtup[nlen - 1] = ( v.spl_leftvalid ) ? gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull) - : gist_form_invalid_tuple( lbknum ); + newtup[nlen - 1] = (v.spl_leftvalid) ? gistFormTuple(giststate, r, v.spl_lattr, v.spl_lattrsize, v.spl_lisnull) + : gist_form_invalid_tuple(lbknum); ItemPointerSetBlockNumber(&(newtup[nlen - 1]->t_tid), lbknum); } GistClearTuplesDeleted(p); - + *len = nlen; return newtup; } @@ -1071,18 +1186,19 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke { Page page; - Assert( BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO ); + Assert(BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO); page = BufferGetPage(buffer); GISTInitBuffer(buffer, 0); gistfillbuffer(r, page, itup, len, FirstOffsetNumber); - if ( !r->rd_istemp ) { - XLogRecPtr recptr; - XLogRecData *rdata; - + if (!r->rd_istemp) + { + XLogRecPtr recptr; + XLogRecData *rdata; + rdata = formUpdateRdata(r->rd_node, GIST_ROOT_BLKNO, - NULL, 0, false, itup, len, key); - + NULL, 0, false, itup, len, key); + START_CRIT_SECTION(); recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_NEW_ROOT, rdata); @@ -1090,7 +1206,8 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke PageSetTLI(page, ThisTimeLineID); END_CRIT_SECTION(); - } else + } + else PageSetLSN(page, XLogRecPtrForTemp); } @@ -1136,4 +1253,3 @@ freeGISTstate(GISTSTATE *giststate) { /* no work */ } - |