diff options
Diffstat (limited to 'src/backend/access/gist/gistxlog.c')
-rw-r--r-- | src/backend/access/gist/gistxlog.c | 131 |
1 files changed, 82 insertions, 49 deletions
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index a029d8f1ec..01dab119b2 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.16 2006/05/10 09:19:54 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.17 2006/05/17 16:34:59 teodor Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" @@ -209,41 +209,33 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) return; } - if (xlrec.data->isemptypage) + if (isnewroot) + GISTInitBuffer(buffer, 0); + else if (xlrec.data->ntodelete) { - while (!PageIsEmpty(page)) - PageIndexTupleDelete(page, FirstOffsetNumber); + int i; - if (xlrec.data->blkno == GIST_ROOT_BLKNO) - GistPageSetLeaf(page); - else - GistPageSetDeleted(page); + for (i = 0; i < xlrec.data->ntodelete; i++) + PageIndexTupleDelete(page, xlrec.todelete[i]); + if (GistPageIsLeaf(page)) + GistMarkTuplesDeleted(page); } - else - { - if (isnewroot) - GISTInitBuffer(buffer, 0); - else if (xlrec.data->ntodelete) - { - int i; - for (i = 0; i < xlrec.data->ntodelete; i++) - PageIndexTupleDelete(page, xlrec.todelete[i]); - if (GistPageIsLeaf(page)) - GistMarkTuplesDeleted(page); - } + /* add tuples */ + if (xlrec.len > 0) + gistfillbuffer(reln, page, xlrec.itup, xlrec.len, InvalidOffsetNumber); - /* add tuples */ - if (xlrec.len > 0) - gistfillbuffer(reln, page, xlrec.itup, xlrec.len, InvalidOffsetNumber); + /* + * special case: leafpage, nothing to insert, nothing to delete, then + * vacuum marks page + */ + if (GistPageIsLeaf(page) && xlrec.len == 0 && xlrec.data->ntodelete == 0) + GistClearTuplesDeleted(page); - /* - * special case: leafpage, nothing to insert, nothing to delete, then - * vacuum marks page - */ - if (GistPageIsLeaf(page) && xlrec.len == 0 && xlrec.data->ntodelete == 0) - GistClearTuplesDeleted(page); - } + if ( !GistPageIsLeaf(page) && PageGetMaxOffsetNumber(page) == InvalidOffsetNumber && xldata->blkno == GIST_ROOT_BLKNO ) + /* all links on non-leaf root page was deleted by vacuum full, + so root page becomes a leaf */ + GistPageSetLeaf(page); GistPageGetOpaque(page)->rightlink = InvalidBlockNumber; PageSetLSN(page, lsn); @@ -253,6 +245,29 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) } static void +gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record) +{ + gistxlogPageDelete *xldata = (gistxlogPageDelete *) XLogRecGetData(record); + Relation reln; + Buffer buffer; + Page page; + + reln = XLogOpenRelation(xldata->node); + buffer = XLogReadBuffer(reln, xldata->blkno, false); + if (!BufferIsValid(buffer)) + return; + + GISTInitBuffer( buffer, 0 ); + page = (Page) BufferGetPage(buffer); + GistPageSetDeleted(page); + + PageSetLSN(page, lsn); + PageSetTLI(page, ThisTimeLineID); + MarkBufferDirty(buffer); + UnlockReleaseBuffer(buffer); +} + +static void decodePageSplitRecord(PageSplitRecord *decoded, XLogRecord *record) { char *begin = XLogRecGetData(record), @@ -382,6 +397,9 @@ gist_redo(XLogRecPtr lsn, XLogRecord *record) case XLOG_GIST_PAGE_UPDATE: gistRedoPageUpdateRecord(lsn, record, false); break; + case XLOG_GIST_PAGE_DELETE: + gistRedoPageDeleteRecord(lsn, record); + break; case XLOG_GIST_NEW_ROOT: gistRedoPageUpdateRecord(lsn, record, true); break; @@ -405,8 +423,10 @@ gist_redo(XLogRecPtr lsn, XLogRecord *record) static void out_target(StringInfo buf, RelFileNode node, ItemPointerData key) { - appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u", - node.spcNode, node.dbNode, node.relNode, + appendStringInfo(buf, "rel %u/%u/%u", + node.spcNode, node.dbNode, node.relNode); + if ( ItemPointerIsValid( &key ) ) + appendStringInfo(buf, "; tid %u/%u", ItemPointerGetBlockNumber(&key), ItemPointerGetOffsetNumber(&key)); } @@ -419,6 +439,14 @@ out_gistxlogPageUpdate(StringInfo buf, gistxlogPageUpdate *xlrec) } static void +out_gistxlogPageDelete(StringInfo buf, gistxlogPageDelete *xlrec) +{ + appendStringInfo(buf, "page_delete: rel %u/%u/%u; blkno %u", + xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode, + xlrec->blkno); +} + +static void out_gistxlogPageSplit(StringInfo buf, gistxlogPageSplit *xlrec) { appendStringInfo(buf, "page_split: "); @@ -438,6 +466,9 @@ gist_desc(StringInfo buf, uint8 xl_info, char *rec) appendStringInfo(buf, "page_update: "); out_gistxlogPageUpdate(buf, (gistxlogPageUpdate *) rec); break; + case XLOG_GIST_PAGE_DELETE: + out_gistxlogPageDelete(buf, (gistxlogPageDelete *) rec); + break; case XLOG_GIST_NEW_ROOT: appendStringInfo(buf, "new_root: "); out_target(buf, ((gistxlogPageUpdate *) rec)->node, ((gistxlogPageUpdate *) rec)->key); @@ -643,7 +674,7 @@ gistContinueInsert(gistIncompleteInsert *insert) * we split root, just copy tuples from old root to new * page */ - parentitup = gistextractbuffer(buffers[numbuffer - 1], + parentitup = gistextractpage(pages[numbuffer - 1], &pituplen); /* sanity check */ @@ -796,7 +827,7 @@ formSplitRdata(RelFileNode node, BlockNumber blkno, bool page_is_leaf, */ XLogRecData * formUpdateRdata(RelFileNode node, Buffer buffer, - OffsetNumber *todelete, int ntodelete, bool emptypage, + OffsetNumber *todelete, int ntodelete, IndexTuple *itup, int ituplen, ItemPointer key) { XLogRecData *rdata; @@ -804,35 +835,37 @@ formUpdateRdata(RelFileNode node, Buffer buffer, int cur, i; - /* ugly wart in API: emptypage causes us to ignore other inputs */ - if (emptypage) - ntodelete = ituplen = 0; - - rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (2 + ituplen)); + rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (3 + ituplen)); xlrec = (gistxlogPageUpdate *) palloc(sizeof(gistxlogPageUpdate)); xlrec->node = node; xlrec->blkno = BufferGetBlockNumber(buffer); xlrec->ntodelete = ntodelete; - xlrec->isemptypage = emptypage; + if (key) xlrec->key = *key; else ItemPointerSetInvalid(&(xlrec->key)); - rdata[0].data = (char *) xlrec; - rdata[0].len = sizeof(gistxlogPageUpdate); - rdata[0].buffer = InvalidBuffer; + rdata[0].buffer = buffer; + rdata[0].buffer_std = true; + rdata[0].data = NULL; + rdata[0].len = 0; rdata[0].next = &(rdata[1]); - rdata[1].data = (char *) todelete; - rdata[1].len = MAXALIGN(sizeof(OffsetNumber) * ntodelete); - rdata[1].buffer = buffer; - rdata[1].buffer_std = true; - rdata[1].next = NULL; + rdata[1].data = (char *) xlrec; + rdata[1].len = sizeof(gistxlogPageUpdate); + rdata[1].buffer = InvalidBuffer; + rdata[1].next = &(rdata[2]); + + rdata[2].data = (char *) todelete; + rdata[2].len = MAXALIGN(sizeof(OffsetNumber) * ntodelete); + rdata[2].buffer = buffer; + rdata[2].buffer_std = true; + rdata[2].next = NULL; /* new tuples */ - cur = 2; + cur = 3; for (i = 0; i < ituplen; i++) { rdata[cur - 1].next = &(rdata[cur]); |