diff options
Diffstat (limited to 'src/backend/access/gist/gistget.c')
-rw-r--r-- | src/backend/access/gist/gistget.c | 190 |
1 files changed, 101 insertions, 89 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index a1fd296dbf..97ae1cfd58 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.74 2008/06/19 00:46:03 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.75 2008/08/23 10:37:24 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -32,63 +32,39 @@ static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan, static void killtuple(Relation r, GISTScanOpaque so, ItemPointer iptr) { - Buffer buffer = so->curbuf; - - for (;;) - { - Page p; - BlockNumber blkno; - OffsetNumber offset, - maxoff; - - LockBuffer(buffer, GIST_SHARE); - gistcheckpage(r, buffer); - p = (Page) BufferGetPage(buffer); + Page p; + OffsetNumber offset; - if (buffer == so->curbuf && XLByteEQ(so->stack->lsn, PageGetLSN(p))) - { - /* page unchanged, so all is simple */ - offset = ItemPointerGetOffsetNumber(iptr); - ItemIdMarkDead(PageGetItemId(p, offset)); - SetBufferCommitInfoNeedsSave(buffer); - LockBuffer(buffer, GIST_UNLOCK); - break; - } + LockBuffer(so->curbuf, GIST_SHARE); + gistcheckpage(r, so->curbuf); + p = (Page) BufferGetPage(so->curbuf); - maxoff = PageGetMaxOffsetNumber(p); + if (XLByteEQ(so->stack->lsn, PageGetLSN(p))) + { + /* page unchanged, so all is simple */ + offset = ItemPointerGetOffsetNumber(iptr); + ItemIdMarkDead(PageGetItemId(p, offset)); + SetBufferCommitInfoNeedsSave(so->curbuf); + } + else + { + OffsetNumber maxoff = PageGetMaxOffsetNumber(p); for (offset = FirstOffsetNumber; offset <= maxoff; offset = OffsetNumberNext(offset)) { - IndexTuple ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset)); + IndexTuple ituple = (IndexTuple) PageGetItem(p, PageGetItemId(p, offset)); if (ItemPointerEquals(&(ituple->t_tid), iptr)) { /* found */ ItemIdMarkDead(PageGetItemId(p, offset)); - SetBufferCommitInfoNeedsSave(buffer); - LockBuffer(buffer, GIST_UNLOCK); - if (buffer != so->curbuf) - ReleaseBuffer(buffer); - return; + SetBufferCommitInfoNeedsSave(so->curbuf); + break; } } - - /* follow right link */ - - /* - * ??? is it good? if tuple dropped by concurrent vacuum, we will read - * all leaf pages... - */ - blkno = GistPageGetOpaque(p)->rightlink; - LockBuffer(buffer, GIST_UNLOCK); - if (buffer != so->curbuf) - ReleaseBuffer(buffer); - - if (blkno == InvalidBlockNumber) - /* can't found, dropped by somebody else */ - return; - buffer = ReadBuffer(r, blkno); } + + LockBuffer(so->curbuf, GIST_UNLOCK); } /* @@ -154,7 +130,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) GISTSearchStack *stk; IndexTuple it; GISTPageOpaque opaque; - bool resetoffset = false; int64 ntids = 0; so = (GISTScanOpaque) scan->opaque; @@ -179,6 +154,50 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) return 0; } + /* + * check stored pointers from last visit + */ + if ( so->nPageData > 0 ) + { + /* + * gistgetmulti never should go here + */ + Assert( tbm == NULL ); + + if ( so->curPageData < so->nPageData ) + { + /* + * pageData is already ordered for scan's direction + */ + scan->xs_ctup.t_self = so->pageData[ so->curPageData ].iptr; + scan->xs_recheck = so->pageData[ so->curPageData ].recheck; + so->curPageData ++; + + return 1; + } + else + { + /* + * Go to the next page + */ + stk = so->stack->next; + pfree(so->stack); + so->stack = stk; + + /* If we're out of stack entries, we're done */ + if (so->stack == NULL) + { + ReleaseBuffer(so->curbuf); + so->curbuf = InvalidBuffer; + return 0; + } + + so->curbuf = ReleaseAndReadBuffer(so->curbuf, + scan->indexRelation, + stk->block); + } + } + for (;;) { CHECK_FOR_INTERRUPTS(); @@ -189,30 +208,25 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) gistcheckpage(scan->indexRelation, so->curbuf); p = BufferGetPage(so->curbuf); opaque = GistPageGetOpaque(p); - resetoffset = false; - if (XLogRecPtrIsInvalid(so->stack->lsn) || !XLByteEQ(so->stack->lsn, PageGetLSN(p))) - { - /* first visit or page changed from last visit, reset offset */ - so->stack->lsn = PageGetLSN(p); - resetoffset = true; - - /* check page split, occured from last visit or visit to parent */ - if (!XLogRecPtrIsInvalid(so->stack->parentlsn) && - XLByteLT(so->stack->parentlsn, opaque->nsn) && - opaque->rightlink != InvalidBlockNumber /* sanity check */ && - (so->stack->next == NULL || so->stack->next->block != opaque->rightlink) /* check if already - added */ ) - { - /* detect page split, follow right link to add pages */ + /* remember lsn to identify page changed for tuple's killing */ + so->stack->lsn = PageGetLSN(p); - stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack)); - stk->next = so->stack->next; - stk->block = opaque->rightlink; - stk->parentlsn = so->stack->parentlsn; - memset(&(stk->lsn), 0, sizeof(GistNSN)); - so->stack->next = stk; - } + /* check page split, occured since visit to parent */ + if (!XLogRecPtrIsInvalid(so->stack->parentlsn) && + XLByteLT(so->stack->parentlsn, opaque->nsn) && + opaque->rightlink != InvalidBlockNumber /* sanity check */ && + (so->stack->next == NULL || so->stack->next->block != opaque->rightlink) /* check if already + added */ ) + { + /* detect page split, follow right link to add pages */ + + stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack)); + stk->next = so->stack->next; + stk->block = opaque->rightlink; + stk->parentlsn = so->stack->parentlsn; + memset(&(stk->lsn), 0, sizeof(GistNSN)); + so->stack->next = stk; } /* if page is empty, then just skip it */ @@ -235,25 +249,13 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) continue; } - if (!GistPageIsLeaf(p) || resetoffset || - !ItemPointerIsValid(&so->curpos)) - { - if (ScanDirectionIsBackward(dir)) - n = PageGetMaxOffsetNumber(p); - else - n = FirstOffsetNumber; - } + if (ScanDirectionIsBackward(dir)) + n = PageGetMaxOffsetNumber(p); else - { - n = ItemPointerGetOffsetNumber(&(so->curpos)); - - if (ScanDirectionIsBackward(dir)) - n = OffsetNumberPrev(n); - else - n = OffsetNumberNext(n); - } + n = FirstOffsetNumber; /* wonderful, we can look at page */ + so->nPageData = so->curPageData = 0; for (;;) { @@ -262,6 +264,18 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) if (!OffsetNumberIsValid(n)) { /* + * If we was called from gistgettuple and current buffer contains + * something matched then make a recursive call - it will return + * ItemPointer from so->pageData. But we save buffer pinned to + * support tuple's killing + */ + if ( !tbm && so->nPageData > 0 ) + { + LockBuffer(so->curbuf, GIST_UNLOCK); + return gistnext(scan, dir, NULL); + } + + /* * We ran out of matching index entries on the current page, * so pop the top stack entry and use it to continue the * search. @@ -306,11 +320,9 @@ gistnext(IndexScanDesc scan, ScanDirection dir, TIDBitmap *tbm) tbm_add_tuples(tbm, &it->t_tid, 1, scan->xs_recheck); else { - scan->xs_ctup.t_self = it->t_tid; - /* scan->xs_recheck is already set */ - - LockBuffer(so->curbuf, GIST_UNLOCK); - return ntids; /* always 1 */ + so->pageData[ so->nPageData ].iptr = it->t_tid; + so->pageData[ so->nPageData ].recheck = scan->xs_recheck; + so->nPageData ++; } } } |