diff options
Diffstat (limited to 'src/backend/access/gist/gistget.c')
-rw-r--r-- | src/backend/access/gist/gistget.c | 183 |
1 files changed, 93 insertions, 90 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index 1e02ec082f4..feeb84d38d7 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.52.2.1 2005/11/22 18:23:03 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.52.2.2 2008/08/23 10:43:58 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -30,62 +30,38 @@ static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan, static void killtuple(Relation r, GISTScanOpaque so, ItemPointer iptr) { - Buffer buffer = so->curbuf; + Page p; + OffsetNumber offset; - for (;;) + LockBuffer(so->curbuf, GIST_SHARE); + p = (Page) BufferGetPage(so->curbuf); + + if (XLByteEQ(so->stack->lsn, PageGetLSN(p))) { - Page p; - BlockNumber blkno; - OffsetNumber offset, - maxoff; - - LockBuffer(buffer, GIST_SHARE); - p = (Page) BufferGetPage(buffer); - - if (buffer == so->curbuf && XLByteEQ(so->stack->lsn, PageGetLSN(p))) - { - /* page unchanged, so all is simple */ - offset = ItemPointerGetOffsetNumber(iptr); - PageGetItemId(p, offset)->lp_flags |= LP_DELETE; - SetBufferCommitInfoNeedsSave(buffer); - LockBuffer(buffer, GIST_UNLOCK); - break; - } - - maxoff = PageGetMaxOffsetNumber(p); + /* page unchanged, so all is simple */ + offset = ItemPointerGetOffsetNumber(iptr); + PageGetItemId(p, offset)->lp_flags |= LP_DELETE; + 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 */ PageGetItemId(p, offset)->lp_flags |= LP_DELETE; - 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); } /* @@ -146,7 +122,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b GISTSearchStack *stk; IndexTuple it; GISTPageOpaque opaque; - bool resetoffset = false; int ntids = 0; so = (GISTScanOpaque) scan->opaque; @@ -171,6 +146,42 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b return 0; } + /* + * check stored pointers from last visit + */ + if ( so->nPageData > 0 ) + { + while( ntids < maxtids && so->curPageData < so->nPageData ) + { + tids[ ntids ] = scan->xs_ctup.t_self = so->pageData[ so->curPageData ]; + + so->curPageData ++; + ntids++; + } + + if ( ntids == maxtids ) + return ntids; + + /* + * 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 ntids; + } + + so->curbuf = ReleaseAndReadBuffer(so->curbuf, + scan->indexRelation, + stk->block); + } + for (;;) { /* First of all, we need lock buffer */ @@ -178,30 +189,25 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b LockBuffer(so->curbuf, GIST_SHARE); p = BufferGetPage(so->curbuf); opaque = GistPageGetOpaque(p); - resetoffset = false; - if (XLogRecPtrIsInvalid(so->stack->lsn) || !XLByteEQ(so->stack->lsn, PageGetLSN(p))) - { - /* page changed from last visit or visit first time , 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 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 */ + + 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 */ @@ -224,24 +230,13 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b continue; } - if (!GistPageIsLeaf(p) || resetoffset || ItemPointerIsValid(&scan->currentItemData) == false) - { - if (ScanDirectionIsBackward(dir)) - n = PageGetMaxOffsetNumber(p); - else - n = FirstOffsetNumber; - } + if (ScanDirectionIsBackward(dir)) + n = PageGetMaxOffsetNumber(p); else - { - n = ItemPointerGetOffsetNumber(&(scan->currentItemData)); - - if (ScanDirectionIsBackward(dir)) - n = OffsetNumberPrev(n); - else - n = OffsetNumberNext(n); - } + n = FirstOffsetNumber; /* wonderfull, we can look at page */ + so->nPageData = so->curPageData = 0; for (;;) { @@ -249,6 +244,20 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b if (!OffsetNumberIsValid(n)) { + while( ntids < maxtids && so->curPageData < so->nPageData ) + { + tids[ ntids ] = scan->xs_ctup.t_self = so->pageData[ so->curPageData ]; + + so->curPageData ++; + ntids++; + } + + if ( ntids == maxtids ) + { + LockBuffer(so->curbuf, GIST_UNLOCK); + return ntids; + } + /* * We ran out of matching index entries on the current page, * so pop the top stack entry and use it to continue the @@ -288,14 +297,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b if (!(ignore_killed_tuples && ItemIdDeleted(PageGetItemId(p, n)))) { it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n)); - tids[ntids] = scan->xs_ctup.t_self = it->t_tid; - ntids++; - - if (ntids == maxtids) - { - LockBuffer(so->curbuf, GIST_UNLOCK); - return ntids; - } + so->pageData[ so->nPageData ] = it->t_tid; + so->nPageData ++; } } else |