diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-08-13 15:39:08 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-09-02 15:10:28 +0300 |
commit | f8f4227976a2cdb8ac7c611e49da03aa9e65e0d2 (patch) | |
tree | 92a7aa95ce72fbac48325761761821f8d7a742ed /src/backend/access/gist/gistxlog.c | |
parent | 26f8b99b248aae989e63ca0969a746f30b0c8c21 (diff) | |
download | postgresql-f8f4227976a2cdb8ac7c611e49da03aa9e65e0d2.tar.gz postgresql-f8f4227976a2cdb8ac7c611e49da03aa9e65e0d2.zip |
Refactor per-page logic common to all redo routines to a new function.
Every redo routine uses the same idiom to determine what to do to a page:
check if there's a backup block for it, and if not read, the buffer if the
block exists, and check its LSN. Refactor that into a common function,
XLogReadBufferForRedo, making all the redo routines shorter and more
readable.
This has no user-visible effect, and makes no changes to the WAL format.
Reviewed by Andres Freund, Alvaro Herrera, Michael Paquier.
Diffstat (limited to 'src/backend/access/gist/gistxlog.c')
-rw-r--r-- | src/backend/access/gist/gistxlog.c | 179 |
1 files changed, 78 insertions, 101 deletions
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index 7d36b2ab6a3..ecc095671df 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -48,31 +48,26 @@ gistRedoClearFollowRight(XLogRecPtr lsn, XLogRecord *record, int block_index, { Buffer buffer; Page page; - - if (record->xl_info & XLR_BKP_BLOCK(block_index)) - buffer = RestoreBackupBlock(lsn, record, block_index, false, true); - else - { - buffer = XLogReadBuffer(node, childblkno, false); - if (!BufferIsValid(buffer)) - return; /* page was deleted, nothing to do */ - } - page = (Page) BufferGetPage(buffer); + XLogRedoAction action; /* - * Note that we still update the page even if page LSN is equal to the LSN - * of this record, because the updated NSN is not included in the full - * page image. + * Note that we still update the page even if it was restored from a full + * page image, because the updated NSN is not included in the image. */ - if (lsn >= PageGetLSN(page)) + action = XLogReadBufferForRedo(lsn, record, block_index, node, childblkno, + &buffer); + if (action == BLK_NEEDS_REDO || action == BLK_RESTORED) { + page = BufferGetPage(buffer); + GistPageSetNSN(page, lsn); GistClearFollowRight(page); PageSetLSN(page, lsn); MarkBufferDirty(buffer); } - UnlockReleaseBuffer(buffer); + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); } /* @@ -87,104 +82,86 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record) Page page; char *data; - /* - * We need to acquire and hold lock on target page while updating the left - * child page. If we have a full-page image of target page, getting the - * lock is a side-effect of restoring that image. Note that even if the - * target page no longer exists, we'll still attempt to replay the change - * on the child page. - */ - if (record->xl_info & XLR_BKP_BLOCK(0)) - buffer = RestoreBackupBlock(lsn, record, 0, false, true); - else - buffer = XLogReadBuffer(xldata->node, xldata->blkno, false); - - /* Fix follow-right data on left child page */ - if (BlockNumberIsValid(xldata->leftchild)) - gistRedoClearFollowRight(lsn, record, 1, - xldata->node, xldata->leftchild); - - /* Done if target page no longer exists */ - if (!BufferIsValid(buffer)) - return; - - /* nothing more to do if page was backed up (and no info to do it with) */ - if (record->xl_info & XLR_BKP_BLOCK(0)) + if (XLogReadBufferForRedo(lsn, record, 0, xldata->node, xldata->blkno, + &buffer) == BLK_NEEDS_REDO) { - UnlockReleaseBuffer(buffer); - return; - } - - page = (Page) BufferGetPage(buffer); - - /* nothing more to do if change already applied */ - if (lsn <= PageGetLSN(page)) - { - UnlockReleaseBuffer(buffer); - return; - } - - data = begin + sizeof(gistxlogPageUpdate); + page = (Page) BufferGetPage(buffer); - /* Delete old tuples */ - if (xldata->ntodelete > 0) - { - int i; - OffsetNumber *todelete = (OffsetNumber *) data; + data = begin + sizeof(gistxlogPageUpdate); - data += sizeof(OffsetNumber) * xldata->ntodelete; + /* Delete old tuples */ + if (xldata->ntodelete > 0) + { + int i; + OffsetNumber *todelete = (OffsetNumber *) data; - for (i = 0; i < xldata->ntodelete; i++) - PageIndexTupleDelete(page, todelete[i]); - if (GistPageIsLeaf(page)) - GistMarkTuplesDeleted(page); - } + data += sizeof(OffsetNumber) * xldata->ntodelete; - /* add tuples */ - if (data - begin < record->xl_len) - { - OffsetNumber off = (PageIsEmpty(page)) ? FirstOffsetNumber : - OffsetNumberNext(PageGetMaxOffsetNumber(page)); + for (i = 0; i < xldata->ntodelete; i++) + PageIndexTupleDelete(page, todelete[i]); + if (GistPageIsLeaf(page)) + GistMarkTuplesDeleted(page); + } - while (data - begin < record->xl_len) + /* add tuples */ + if (data - begin < record->xl_len) { - IndexTuple itup = (IndexTuple) data; - Size sz = IndexTupleSize(itup); - OffsetNumber l; - - data += sz; + OffsetNumber off = (PageIsEmpty(page)) ? FirstOffsetNumber : + OffsetNumberNext(PageGetMaxOffsetNumber(page)); + + while (data - begin < record->xl_len) + { + IndexTuple itup = (IndexTuple) data; + Size sz = IndexTupleSize(itup); + OffsetNumber l; + + data += sz; + + l = PageAddItem(page, (Item) itup, sz, off, false, false); + if (l == InvalidOffsetNumber) + elog(ERROR, "failed to add item to GiST index page, size %d bytes", + (int) sz); + off++; + } + } + else + { + /* + * special case: leafpage, nothing to insert, nothing to delete, + * then vacuum marks page + */ + if (GistPageIsLeaf(page) && xldata->ntodelete == 0) + GistClearTuplesDeleted(page); + } - l = PageAddItem(page, (Item) itup, sz, off, false, false); - if (l == InvalidOffsetNumber) - elog(ERROR, "failed to add item to GiST index page, size %d bytes", - (int) sz); - off++; + 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); } - } - else - { - /* - * special case: leafpage, nothing to insert, nothing to delete, then - * vacuum marks page - */ - if (GistPageIsLeaf(page) && xldata->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); + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); } - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - UnlockReleaseBuffer(buffer); + /* + * Fix follow-right data on left child page + * + * This must be done while still holding the lock on the target page. Note + * that even if the target page no longer exists, we still attempt to + * replay the change on the child page. + */ + if (BlockNumberIsValid(xldata->leftchild)) + gistRedoClearFollowRight(lsn, record, 1, + xldata->node, xldata->leftchild); + + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); } static void |