From a213f1ee6c5a1bbe1f074ca201975e76ad2ed50c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 12 Jun 2008 09:12:31 +0000 Subject: [PATCH] Refactor XLogOpenRelation() and XLogReadBuffer() in preparation for relation forks. XLogOpenRelation() and the associated light-weight relation cache in xlogutils.c is gone, and XLogReadBuffer() now takes a RelFileNode as argument, instead of Relation. For functions that still need a Relation struct during WAL replay, there's a new function called CreateFakeRelcacheEntry() that returns a fake entry like XLogOpenRelation() used to. --- src/backend/access/gin/ginxlog.c | 42 ++-- src/backend/access/gist/gist.c | 6 +- src/backend/access/gist/gistutil.c | 18 +- src/backend/access/gist/gistvacuum.c | 4 +- src/backend/access/gist/gistxlog.c | 32 ++- src/backend/access/heap/heapam.c | 41 ++-- src/backend/access/heap/pruneheap.c | 6 +- src/backend/access/nbtree/nbtxlog.c | 61 +++-- src/backend/access/transam/xlog.c | 15 +- src/backend/access/transam/xlogutils.c | 306 +++++++------------------ src/backend/commands/sequence.c | 6 +- src/backend/storage/buffer/bufmgr.c | 109 ++++++--- src/backend/storage/buffer/localbuf.c | 8 +- src/backend/storage/smgr/smgr.c | 9 +- src/backend/utils/init/flatfiles.c | 26 +-- src/include/access/gist_private.h | 6 +- src/include/access/heapam.h | 4 +- src/include/access/xlogutils.h | 10 +- src/include/storage/buf_internals.h | 9 +- src/include/storage/bufmgr.h | 4 +- 20 files changed, 295 insertions(+), 427 deletions(-) diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 8b3d75ce59..428c956c7c 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.13 2008/05/12 00:00:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.14 2008/06/12 09:12:29 heikki Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" @@ -71,12 +71,10 @@ static void ginRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record) { RelFileNode *node = (RelFileNode *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; - reln = XLogOpenRelation(*node); - buffer = XLogReadBuffer(reln, GIN_ROOT_BLKNO, true); + buffer = XLogReadBuffer(*node, GIN_ROOT_BLKNO, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -94,12 +92,10 @@ ginRedoCreatePTree(XLogRecPtr lsn, XLogRecord *record) { ginxlogCreatePostingTree *data = (ginxlogCreatePostingTree *) XLogRecGetData(record); ItemPointerData *items = (ItemPointerData *) (XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree)); - Relation reln; Buffer buffer; Page page; - reln = XLogOpenRelation(data->node); - buffer = XLogReadBuffer(reln, data->blkno, true); + buffer = XLogReadBuffer(data->node, data->blkno, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -118,7 +114,6 @@ static void ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) { ginxlogInsert *data = (ginxlogInsert *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; @@ -126,8 +121,7 @@ ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(data->node); - buffer = XLogReadBuffer(reln, data->blkno, false); + buffer = XLogReadBuffer(data->node, data->blkno, false); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -228,26 +222,23 @@ static void ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) { ginxlogSplit *data = (ginxlogSplit *) XLogRecGetData(record); - Relation reln; Buffer lbuffer, rbuffer; Page lpage, rpage; uint32 flags = 0; - reln = XLogOpenRelation(data->node); - if (data->isLeaf) flags |= GIN_LEAF; if (data->isData) flags |= GIN_DATA; - lbuffer = XLogReadBuffer(reln, data->lblkno, data->isRootSplit); + lbuffer = XLogReadBuffer(data->node, data->lblkno, data->isRootSplit); Assert(BufferIsValid(lbuffer)); lpage = (Page) BufferGetPage(lbuffer); GinInitBuffer(lbuffer, flags); - rbuffer = XLogReadBuffer(reln, data->rblkno, true); + rbuffer = XLogReadBuffer(data->node, data->rblkno, true); Assert(BufferIsValid(rbuffer)); rpage = (Page) BufferGetPage(rbuffer); GinInitBuffer(rbuffer, flags); @@ -319,7 +310,7 @@ ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) if (data->isRootSplit) { - Buffer rootBuf = XLogReadBuffer(reln, data->rootBlkno, false); + Buffer rootBuf = XLogReadBuffer(data->node, data->rootBlkno, false); Page rootPage = BufferGetPage(rootBuf); GinInitBuffer(rootBuf, flags & ~GIN_LEAF); @@ -352,7 +343,6 @@ static void ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record) { ginxlogVacuumPage *data = (ginxlogVacuumPage *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; @@ -360,8 +350,7 @@ ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(data->node); - buffer = XLogReadBuffer(reln, data->blkno, false); + buffer = XLogReadBuffer(data->node, data->blkno, false); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -403,15 +392,12 @@ static void ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) { ginxlogDeletePage *data = (ginxlogDeletePage *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; - reln = XLogOpenRelation(data->node); - if (!(record->xl_info & XLR_BKP_BLOCK_1)) { - buffer = XLogReadBuffer(reln, data->blkno, false); + buffer = XLogReadBuffer(data->node, data->blkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); GinPageGetOpaque(page)->flags = GIN_DELETED; @@ -423,7 +409,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) if (!(record->xl_info & XLR_BKP_BLOCK_2)) { - buffer = XLogReadBuffer(reln, data->parentBlkno, false); + buffer = XLogReadBuffer(data->node, data->parentBlkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); Assert(!GinPageIsLeaf(page)); @@ -436,7 +422,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) if (!(record->xl_info & XLR_BKP_BLOCK_3) && data->leftBlkno != InvalidBlockNumber) { - buffer = XLogReadBuffer(reln, data->leftBlkno, false); + buffer = XLogReadBuffer(data->node, data->leftBlkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); GinPageGetOpaque(page)->rightlink = data->rightLink; @@ -557,9 +543,9 @@ ginContinueSplit(ginIncompleteSplit *split) * elog(NOTICE,"ginContinueSplit root:%u l:%u r:%u", split->rootBlkno, * split->leftBlkno, split->rightBlkno); */ - reln = XLogOpenRelation(split->node); + buffer = XLogReadBuffer(split->node, split->leftBlkno, false); - buffer = XLogReadBuffer(reln, split->leftBlkno, false); + reln = CreateFakeRelcacheEntry(split->node); if (split->rootBlkno == GIN_ROOT_BLKNO) { @@ -581,6 +567,8 @@ ginContinueSplit(ginIncompleteSplit *split) GinPageGetOpaque(page)->maxoff))->key; } + FreeFakeRelcacheEntry(reln); + btree.rightblkno = split->rightBlkno; stack.blkno = split->leftBlkno; diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 1638c4cf0c..7dd981a490 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.150 2008/05/12 00:00:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.151 2008/06/12 09:12:29 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -462,7 +462,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) if (!is_leaf) PageIndexTupleDelete(state->stack->page, state->stack->childoffnum); - gistfillbuffer(state->r, state->stack->page, state->itup, state->ituplen, InvalidOffsetNumber); + gistfillbuffer(state->stack->page, state->itup, state->ituplen, InvalidOffsetNumber); MarkBufferDirty(state->stack->buffer); @@ -1008,7 +1008,7 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke START_CRIT_SECTION(); GISTInitBuffer(buffer, 0); - gistfillbuffer(r, page, itup, len, FirstOffsetNumber); + gistfillbuffer(page, itup, len, FirstOffsetNumber); MarkBufferDirty(buffer); diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index 9847e412e2..ef60b6b96d 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.26 2008/05/12 00:00:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.27 2008/06/12 09:12:29 heikki Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" @@ -27,11 +27,10 @@ static Datum attrS[INDEX_MAX_KEYS]; static bool isnullS[INDEX_MAX_KEYS]; /* - * Write itup vector to page, has no control of free space + * Write itup vector to page, has no control of free space. */ -OffsetNumber -gistfillbuffer(Relation r, Page page, IndexTuple *itup, - int len, OffsetNumber off) +void +gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off) { OffsetNumber l = InvalidOffsetNumber; int i; @@ -42,14 +41,13 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup, for (i = 0; i < len; i++) { - l = PageAddItem(page, (Item) itup[i], IndexTupleSize(itup[i]), - off, false, false); + Size sz = IndexTupleSize(itup[i]); + l = PageAddItem(page, (Item) itup[i], sz, off, false, false); if (l == InvalidOffsetNumber) - elog(ERROR, "failed to add item to index page in \"%s\"", - RelationGetRelationName(r)); + elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes", + i, len, sz); off++; } - return l; } /* diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 809b5ce7cc..d929962af2 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.35 2008/05/12 00:00:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.36 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -403,7 +403,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion) } else /* enough free space */ - gistfillbuffer(gv->index, tempPage, addon, curlenaddon, InvalidOffsetNumber); + gistfillbuffer(tempPage, addon, curlenaddon, InvalidOffsetNumber); } } diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index abe912dd88..801c6e7117 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.28 2008/05/12 00:00:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.29 2008/06/12 09:12:30 heikki Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" @@ -189,7 +189,6 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) { gistxlogPageUpdate *xldata = (gistxlogPageUpdate *) XLogRecGetData(record); PageUpdateRecord xlrec; - Relation reln; Buffer buffer; Page page; @@ -208,8 +207,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) decodePageUpdateRecord(&xlrec, record); - reln = XLogOpenRelation(xlrec.data->node); - buffer = XLogReadBuffer(reln, xlrec.data->blkno, false); + buffer = XLogReadBuffer(xlrec.data->node, xlrec.data->blkno, false); if (!BufferIsValid(buffer)) return; page = (Page) BufferGetPage(buffer); @@ -234,7 +232,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) /* add tuples */ if (xlrec.len > 0) - gistfillbuffer(reln, page, xlrec.itup, xlrec.len, InvalidOffsetNumber); + gistfillbuffer(page, xlrec.itup, xlrec.len, InvalidOffsetNumber); /* * special case: leafpage, nothing to insert, nothing to delete, then @@ -262,7 +260,6 @@ static void gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record) { gistxlogPageDelete *xldata = (gistxlogPageDelete *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; @@ -270,8 +267,7 @@ gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xldata->node); - buffer = XLogReadBuffer(reln, xldata->blkno, false); + buffer = XLogReadBuffer(xldata->node, xldata->blkno, false); if (!BufferIsValid(buffer)) return; @@ -319,14 +315,12 @@ static void gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) { PageSplitRecord xlrec; - Relation reln; Buffer buffer; Page page; int i; int flags; decodePageSplitRecord(&xlrec, record); - reln = XLogOpenRelation(xlrec.data->node); flags = xlrec.data->origleaf ? F_LEAF : 0; /* loop around all pages */ @@ -334,7 +328,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) { NewPage *newpage = xlrec.page + i; - buffer = XLogReadBuffer(reln, newpage->header->blkno, true); + buffer = XLogReadBuffer(xlrec.data->node, newpage->header->blkno, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -342,7 +336,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) GISTInitBuffer(buffer, flags); /* and fill it */ - gistfillbuffer(reln, page, newpage->itup, newpage->header->num, FirstOffsetNumber); + gistfillbuffer(page, newpage->itup, newpage->header->num, FirstOffsetNumber); PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); @@ -361,12 +355,10 @@ static void gistRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record) { RelFileNode *node = (RelFileNode *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; - reln = XLogOpenRelation(*node); - buffer = XLogReadBuffer(reln, GIST_ROOT_BLKNO, true); + buffer = XLogReadBuffer(*node, GIST_ROOT_BLKNO, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -602,7 +594,7 @@ gistContinueInsert(gistIncompleteInsert *insert) lenitup; Relation index; - index = XLogOpenRelation(insert->node); + index = CreateFakeRelcacheEntry(insert->node); /* * needed vector itup never will be more than initial lenblkno+2, because @@ -624,7 +616,7 @@ gistContinueInsert(gistIncompleteInsert *insert) * it was split root, so we should only make new root. it can't be * simple insert into root, we should replace all content of root. */ - Buffer buffer = XLogReadBuffer(index, GIST_ROOT_BLKNO, true); + Buffer buffer = XLogReadBuffer(insert->node, GIST_ROOT_BLKNO, true); gistnewroot(index, buffer, itup, lenitup, NULL); UnlockReleaseBuffer(buffer); @@ -703,7 +695,7 @@ gistContinueInsert(gistIncompleteInsert *insert) LockBuffer(buffers[numbuffer], GIST_EXCLUSIVE); GISTInitBuffer(buffers[numbuffer], 0); pages[numbuffer] = BufferGetPage(buffers[numbuffer]); - gistfillbuffer(index, pages[numbuffer], itup, lenitup, FirstOffsetNumber); + gistfillbuffer(pages[numbuffer], itup, lenitup, FirstOffsetNumber); numbuffer++; if (BufferGetBlockNumber(buffers[0]) == GIST_ROOT_BLKNO) @@ -749,7 +741,7 @@ gistContinueInsert(gistIncompleteInsert *insert) for (j = 0; j < ntodelete; j++) PageIndexTupleDelete(pages[0], todelete[j]); - gistfillbuffer(index, pages[0], itup, lenitup, InvalidOffsetNumber); + gistfillbuffer(pages[0], itup, lenitup, InvalidOffsetNumber); rdata = formUpdateRdata(index->rd_node, buffers[0], todelete, ntodelete, @@ -794,6 +786,8 @@ gistContinueInsert(gistIncompleteInsert *insert) } } + FreeFakeRelcacheEntry(index); + ereport(LOG, (errmsg("index %u/%u/%u needs VACUUM FULL or REINDEX to finish crash recovery", insert->node.spcNode, insert->node.dbNode, insert->node.relNode), diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index c0b46e20e7..9a29a0f209 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.258 2008/06/08 22:00:47 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.259 2008/06/12 09:12:30 heikki Exp $ * * * INTERFACE ROUTINES @@ -3944,7 +3944,6 @@ static void heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) { xl_heap_clean *xlrec = (xl_heap_clean *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; OffsetNumber *end; @@ -3958,8 +3957,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, xlrec->block, false); + buffer = XLogReadBuffer(xlrec->node, xlrec->block, false); if (!BufferIsValid(buffer)) return; page = (Page) BufferGetPage(buffer); @@ -3980,7 +3978,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) Assert(nunused >= 0); /* Update all item pointers per the record, and repair fragmentation */ - heap_page_prune_execute(reln, buffer, + heap_page_prune_execute(buffer, redirected, nredirected, nowdead, ndead, nowunused, nunused, @@ -4002,15 +4000,13 @@ heap_xlog_freeze(XLogRecPtr lsn, XLogRecord *record) { xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record); TransactionId cutoff_xid = xlrec->cutoff_xid; - Relation reln; Buffer buffer; Page page; if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, xlrec->block, false); + buffer = XLogReadBuffer(xlrec->node, xlrec->block, false); if (!BufferIsValid(buffer)) return; page = (Page) BufferGetPage(buffer); @@ -4050,7 +4046,6 @@ static void heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record) { xl_heap_newpage *xlrec = (xl_heap_newpage *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; @@ -4058,8 +4053,7 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record) * Note: the NEWPAGE log record is used for both heaps and indexes, so do * not do anything that assumes we are touching a heap. */ - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, xlrec->blkno, true); + buffer = XLogReadBuffer(xlrec->node, xlrec->blkno, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -4076,7 +4070,6 @@ static void heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record) { xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; OffsetNumber offnum; @@ -4086,8 +4079,7 @@ heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xlrec->target.node); - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (!BufferIsValid(buffer)) @@ -4133,7 +4125,6 @@ static void heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) { xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; OffsetNumber offnum; @@ -4149,11 +4140,9 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xlrec->target.node); - if (record->xl_info & XLOG_HEAP_INIT_PAGE) { - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), true); Assert(BufferIsValid(buffer)); @@ -4163,7 +4152,7 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) } else { - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (!BufferIsValid(buffer)) @@ -4216,7 +4205,6 @@ static void heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update) { xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); - Relation reln = XLogOpenRelation(xlrec->target.node); Buffer buffer; bool samepage = (ItemPointerGetBlockNumber(&(xlrec->newtid)) == ItemPointerGetBlockNumber(&(xlrec->target.tid))); @@ -4242,7 +4230,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update) /* Deal with old tuple version */ - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (!BufferIsValid(buffer)) @@ -4317,7 +4305,7 @@ newt:; if (record->xl_info & XLOG_HEAP_INIT_PAGE) { - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->newtid)), true); Assert(BufferIsValid(buffer)); @@ -4327,7 +4315,7 @@ newt:; } else { - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->newtid)), false); if (!BufferIsValid(buffer)) @@ -4399,7 +4387,6 @@ static void heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record) { xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; OffsetNumber offnum; @@ -4409,8 +4396,7 @@ heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - reln = XLogOpenRelation(xlrec->target.node); - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (!BufferIsValid(buffer)) @@ -4458,7 +4444,6 @@ static void heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record) { xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); - Relation reln = XLogOpenRelation(xlrec->target.node); Buffer buffer; Page page; OffsetNumber offnum; @@ -4470,7 +4455,7 @@ heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record) if (record->xl_info & XLR_BKP_BLOCK_1) return; - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (!BufferIsValid(buffer)) diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index f86c53aad2..2196301c71 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.13 2008/06/08 22:00:47 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.14 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -225,7 +225,7 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin, * and update the page's hint bit about whether it has free line * pointers. */ - heap_page_prune_execute(relation, buffer, + heap_page_prune_execute(buffer, prstate.redirected, prstate.nredirected, prstate.nowdead, prstate.ndead, prstate.nowunused, prstate.nunused, @@ -696,7 +696,7 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum) * arguments are identical to those of log_heap_clean(). */ void -heap_page_prune_execute(Relation reln, Buffer buffer, +heap_page_prune_execute(Buffer buffer, OffsetNumber *redirected, int nredirected, OffsetNumber *nowdead, int ndead, OffsetNumber *nowunused, int nunused, diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c index 72d292d096..49021e4885 100644 --- a/src/backend/access/nbtree/nbtxlog.c +++ b/src/backend/access/nbtree/nbtxlog.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.51 2008/05/12 00:00:45 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.52 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -150,7 +150,7 @@ _bt_restore_page(Page page, char *from, int len) } static void -_bt_restore_meta(Relation reln, XLogRecPtr lsn, +_bt_restore_meta(RelFileNode rnode, XLogRecPtr lsn, BlockNumber root, uint32 level, BlockNumber fastroot, uint32 fastlevel) { @@ -159,7 +159,7 @@ _bt_restore_meta(Relation reln, XLogRecPtr lsn, BTMetaPageData *md; BTPageOpaque pageop; - metabuf = XLogReadBuffer(reln, BTREE_METAPAGE, true); + metabuf = XLogReadBuffer(rnode, BTREE_METAPAGE, true); Assert(BufferIsValid(metabuf)); metapg = BufferGetPage(metabuf); @@ -194,7 +194,6 @@ btree_xlog_insert(bool isleaf, bool ismeta, XLogRecPtr lsn, XLogRecord *record) { xl_btree_insert *xlrec = (xl_btree_insert *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; char *datapos; @@ -220,11 +219,9 @@ btree_xlog_insert(bool isleaf, bool ismeta, if ((record->xl_info & XLR_BKP_BLOCK_1) && !ismeta && isleaf) return; /* nothing to do */ - reln = XLogOpenRelation(xlrec->target.node); - if (!(record->xl_info & XLR_BKP_BLOCK_1)) { - buffer = XLogReadBuffer(reln, + buffer = XLogReadBuffer(xlrec->target.node, ItemPointerGetBlockNumber(&(xlrec->target.tid)), false); if (BufferIsValid(buffer)) @@ -251,7 +248,7 @@ btree_xlog_insert(bool isleaf, bool ismeta, } if (ismeta) - _bt_restore_meta(reln, lsn, + _bt_restore_meta(xlrec->target.node, lsn, md.root, md.level, md.fastroot, md.fastlevel); @@ -265,7 +262,6 @@ btree_xlog_split(bool onleft, bool isroot, XLogRecPtr lsn, XLogRecord *record) { xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record); - Relation reln; Buffer rbuf; Page rpage; BTPageOpaque ropaque; @@ -277,8 +273,6 @@ btree_xlog_split(bool onleft, bool isroot, Item left_hikey = NULL; Size left_hikeysz = 0; - reln = XLogOpenRelation(xlrec->node); - datapos = (char *) xlrec + SizeOfBtreeSplit; datalen = record->xl_len - SizeOfBtreeSplit; @@ -328,7 +322,7 @@ btree_xlog_split(bool onleft, bool isroot, } /* Reconstruct right (new) sibling from scratch */ - rbuf = XLogReadBuffer(reln, xlrec->rightsib, true); + rbuf = XLogReadBuffer(xlrec->node, xlrec->rightsib, true); Assert(BufferIsValid(rbuf)); rpage = (Page) BufferGetPage(rbuf); @@ -369,7 +363,7 @@ btree_xlog_split(bool onleft, bool isroot, */ if (!(record->xl_info & XLR_BKP_BLOCK_1)) { - Buffer lbuf = XLogReadBuffer(reln, xlrec->leftsib, false); + Buffer lbuf = XLogReadBuffer(xlrec->node, xlrec->leftsib, false); if (BufferIsValid(lbuf)) { @@ -439,7 +433,7 @@ btree_xlog_split(bool onleft, bool isroot, /* Fix left-link of the page to the right of the new right sibling */ if (xlrec->rnext != P_NONE && !(record->xl_info & XLR_BKP_BLOCK_2)) { - Buffer buffer = XLogReadBuffer(reln, xlrec->rnext, false); + Buffer buffer = XLogReadBuffer(xlrec->node, xlrec->rnext, false); if (BufferIsValid(buffer)) { @@ -468,7 +462,6 @@ static void btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record) { xl_btree_delete *xlrec; - Relation reln; Buffer buffer; Page page; BTPageOpaque opaque; @@ -477,8 +470,7 @@ btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record) return; xlrec = (xl_btree_delete *) XLogRecGetData(record); - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, xlrec->block, false); + buffer = XLogReadBuffer(xlrec->node, xlrec->block, false); if (!BufferIsValid(buffer)) return; page = (Page) BufferGetPage(buffer); @@ -517,7 +509,6 @@ static void btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) { xl_btree_delete_page *xlrec = (xl_btree_delete_page *) XLogRecGetData(record); - Relation reln; BlockNumber parent; BlockNumber target; BlockNumber leftsib; @@ -526,7 +517,6 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) Page page; BTPageOpaque pageop; - reln = XLogOpenRelation(xlrec->target.node); parent = ItemPointerGetBlockNumber(&(xlrec->target.tid)); target = xlrec->deadblk; leftsib = xlrec->leftblk; @@ -535,7 +525,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) /* parent page */ if (!(record->xl_info & XLR_BKP_BLOCK_1)) { - buffer = XLogReadBuffer(reln, parent, false); + buffer = XLogReadBuffer(xlrec->target.node, parent, false); if (BufferIsValid(buffer)) { page = (Page) BufferGetPage(buffer); @@ -581,7 +571,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) /* Fix left-link of right sibling */ if (!(record->xl_info & XLR_BKP_BLOCK_2)) { - buffer = XLogReadBuffer(reln, rightsib, false); + buffer = XLogReadBuffer(xlrec->target.node, rightsib, false); if (BufferIsValid(buffer)) { page = (Page) BufferGetPage(buffer); @@ -607,7 +597,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) { if (leftsib != P_NONE) { - buffer = XLogReadBuffer(reln, leftsib, false); + buffer = XLogReadBuffer(xlrec->target.node, leftsib, false); if (BufferIsValid(buffer)) { page = (Page) BufferGetPage(buffer); @@ -630,7 +620,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) } /* Rewrite target page as empty deleted page */ - buffer = XLogReadBuffer(reln, target, true); + buffer = XLogReadBuffer(xlrec->target.node, target, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -655,7 +645,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) memcpy(&md, (char *) xlrec + SizeOfBtreeDeletePage, sizeof(xl_btree_metadata)); - _bt_restore_meta(reln, lsn, + _bt_restore_meta(xlrec->target.node, lsn, md.root, md.level, md.fastroot, md.fastlevel); } @@ -672,14 +662,12 @@ static void btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record) { xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record); - Relation reln; Buffer buffer; Page page; BTPageOpaque pageop; BlockNumber downlink = 0; - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, xlrec->rootblk, true); + buffer = XLogReadBuffer(xlrec->node, xlrec->rootblk, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -711,7 +699,7 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record) MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer); - _bt_restore_meta(reln, lsn, + _bt_restore_meta(xlrec->node, lsn, xlrec->rootblk, xlrec->level, xlrec->rootblk, xlrec->level); @@ -904,9 +892,7 @@ btree_xlog_cleanup(void) foreach(l, incomplete_actions) { bt_incomplete_action *action = (bt_incomplete_action *) lfirst(l); - Relation reln; - reln = XLogOpenRelation(action->node); if (action->is_split) { /* finish an incomplete split */ @@ -917,14 +903,15 @@ btree_xlog_cleanup(void) BTPageOpaque lpageop, rpageop; bool is_only; + Relation reln; - lbuf = XLogReadBuffer(reln, action->leftblk, false); + lbuf = XLogReadBuffer(action->node, action->leftblk, false); /* failure is impossible because we wrote this page earlier */ if (!BufferIsValid(lbuf)) elog(PANIC, "btree_xlog_cleanup: left block unfound"); lpage = (Page) BufferGetPage(lbuf); lpageop = (BTPageOpaque) PageGetSpecialPointer(lpage); - rbuf = XLogReadBuffer(reln, action->rightblk, false); + rbuf = XLogReadBuffer(action->node, action->rightblk, false); /* failure is impossible because we wrote this page earlier */ if (!BufferIsValid(rbuf)) elog(PANIC, "btree_xlog_cleanup: right block unfound"); @@ -934,18 +921,26 @@ btree_xlog_cleanup(void) /* if the pages are all of their level, it's a only-page split */ is_only = P_LEFTMOST(lpageop) && P_RIGHTMOST(rpageop); + reln = CreateFakeRelcacheEntry(action->node); _bt_insert_parent(reln, lbuf, rbuf, NULL, action->is_root, is_only); + FreeFakeRelcacheEntry(reln); } else { /* finish an incomplete deletion (of a half-dead page) */ Buffer buf; - buf = XLogReadBuffer(reln, action->delblk, false); + buf = XLogReadBuffer(action->node, action->delblk, false); if (BufferIsValid(buf)) + { + Relation reln; + + reln = CreateFakeRelcacheEntry(action->node); if (_bt_pagedel(reln, buf, NULL, true) == 0) elog(PANIC, "btree_xlog_cleanup: _bt_pagdel failed"); + FreeFakeRelcacheEntry(reln); + } } } incomplete_actions = NIL; diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 26f0fa7293..4c9b7872ca 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.313 2008/06/08 22:00:47 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.314 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -2840,7 +2840,6 @@ CleanupBackupHistory(void) static void RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn) { - Relation reln; Buffer buffer; Page page; BkpBlock bkpb; @@ -2856,8 +2855,7 @@ RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn) memcpy(&bkpb, blk, sizeof(BkpBlock)); blk += sizeof(BkpBlock); - reln = XLogOpenRelation(bkpb.node); - buffer = XLogReadBuffer(reln, bkpb.block, true); + buffer = XLogReadBuffer(bkpb.node, bkpb.block, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); @@ -5064,9 +5062,7 @@ StartupXLOG(void) BACKUP_LABEL_FILE, BACKUP_LABEL_OLD))); } - /* Start up the recovery environment */ - XLogInitRelationCache(); - + /* Initialize resource managers */ for (rmid = 0; rmid <= RM_MAX_ID; rmid++) { if (RmgrTable[rmid].rm_startup != NULL) @@ -5330,11 +5326,6 @@ StartupXLOG(void) * allows some extra error checking in xlog_redo. */ CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); - - /* - * Close down recovery environment - */ - XLogCloseRelationCache(); } /* diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index a73bdb52a4..19758700e7 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.54 2008/06/08 22:00:47 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.55 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -190,6 +190,9 @@ XLogCheckInvalidPages(void) if (foundone) elog(PANIC, "WAL contains references to invalid pages"); + + hash_destroy(invalid_page_tab); + invalid_page_tab = NULL; } @@ -218,27 +221,40 @@ XLogCheckInvalidPages(void) * at the end of WAL replay.) */ Buffer -XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) +XLogReadBuffer(RelFileNode rnode, BlockNumber blkno, bool init) { - BlockNumber lastblock = RelationGetNumberOfBlocks(reln); + BlockNumber lastblock; Buffer buffer; + SMgrRelation smgr; Assert(blkno != P_NEW); + /* Open the relation at smgr level */ + smgr = smgropen(rnode); + + /* + * Create the target file if it doesn't already exist. This lets us cope + * if the replay sequence contains writes to a relation that is later + * deleted. (The original coding of this routine would instead suppress + * the writes, but that seems like it risks losing valuable data if the + * filesystem loses an inode during a crash. Better to write the data + * until we are actually told to delete the file.) + */ + smgrcreate(smgr, false, true); + + lastblock = smgrnblocks(smgr); + if (blkno < lastblock) { /* page exists in file */ - if (init) - buffer = ReadOrZeroBuffer(reln, blkno); - else - buffer = ReadBuffer(reln, blkno); + buffer = ReadBufferWithoutRelcache(rnode, false, blkno, init); } else { /* hm, page doesn't exist in file */ if (!init) { - log_invalid_page(reln->rd_node, blkno, false); + log_invalid_page(rnode, blkno, false); return InvalidBuffer; } /* OK to extend the file */ @@ -249,7 +265,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) { if (buffer != InvalidBuffer) ReleaseBuffer(buffer); - buffer = ReadBuffer(reln, P_NEW); + buffer = ReadBufferWithoutRelcache(rnode, false, P_NEW, false); lastblock++; } Assert(BufferGetBlockNumber(buffer) == blkno); @@ -265,7 +281,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) if (PageIsNew((PageHeader) page)) { UnlockReleaseBuffer(buffer); - log_invalid_page(reln->rd_node, blkno, true); + log_invalid_page(rnode, blkno, true); return InvalidBuffer; } } @@ -275,226 +291,81 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) /* - * Lightweight "Relation" cache --- this substitutes for the normal relcache - * during XLOG replay. + * Struct actually returned by XLogFakeRelcacheEntry, though the declared + * return type is Relation. */ - -typedef struct XLogRelDesc +typedef struct { - RelationData reldata; - struct XLogRelDesc *lessRecently; - struct XLogRelDesc *moreRecently; -} XLogRelDesc; + RelationData reldata; /* Note: this must be first */ + FormData_pg_class pgc; +} FakeRelCacheEntryData; -typedef struct XLogRelCacheEntry +typedef FakeRelCacheEntryData *FakeRelCacheEntry; + +/* + * Create a fake relation cache entry for a physical relation + * + * It's often convenient to use the same functions in XLOG replay as in the + * main codepath, but those functions typically work with a relcache entry. + * We don't have a working relation cache during XLOG replay, but this + * function can be used to create a fake relcache entry instead. Only the + * fields related to physical storage, like rd_rel, are initialized, so the + * fake entry is only usable in low-level operations like ReadBuffer(). + * + * Caller must free the returned entry with FreeFakeRelcacheEntry(). + */ +Relation +CreateFakeRelcacheEntry(RelFileNode rnode) { - RelFileNode rnode; - XLogRelDesc *rdesc; -} XLogRelCacheEntry; + FakeRelCacheEntry fakeentry; + Relation rel; -static HTAB *_xlrelcache; -static XLogRelDesc *_xlrelarr = NULL; -static Form_pg_class _xlpgcarr = NULL; -static int _xlast = 0; -static int _xlcnt = 0; + /* Allocate the Relation struct and all related space in one block. */ + fakeentry = palloc0(sizeof(FakeRelCacheEntryData)); + rel = (Relation) fakeentry; -#define _XLOG_RELCACHESIZE 512 + rel->rd_rel = &fakeentry->pgc; + rel->rd_node = rnode; -static void -_xl_init_rel_cache(void) -{ - HASHCTL ctl; + /* We don't know the name of the relation; use relfilenode instead */ + sprintf(RelationGetRelationName(rel), "%u", rnode.relNode); - _xlcnt = _XLOG_RELCACHESIZE; - _xlast = 0; - _xlrelarr = (XLogRelDesc *) malloc(sizeof(XLogRelDesc) * _xlcnt); - memset(_xlrelarr, 0, sizeof(XLogRelDesc) * _xlcnt); - _xlpgcarr = (Form_pg_class) malloc(sizeof(FormData_pg_class) * _xlcnt); - memset(_xlpgcarr, 0, sizeof(FormData_pg_class) * _xlcnt); + /* + * We set up the lockRelId in case anything tries to lock the dummy + * relation. Note that this is fairly bogus since relNode may be + * different from the relation's OID. It shouldn't really matter + * though, since we are presumably running by ourselves and can't have + * any lock conflicts ... + */ + rel->rd_lockInfo.lockRelId.dbId = rnode.dbNode; + rel->rd_lockInfo.lockRelId.relId = rnode.relNode; - _xlrelarr[0].moreRecently = &(_xlrelarr[0]); - _xlrelarr[0].lessRecently = &(_xlrelarr[0]); + rel->rd_targblock = InvalidBlockNumber; + rel->rd_smgr = NULL; - memset(&ctl, 0, sizeof(ctl)); - ctl.keysize = sizeof(RelFileNode); - ctl.entrysize = sizeof(XLogRelCacheEntry); - ctl.hash = tag_hash; - - _xlrelcache = hash_create("XLOG relcache", _XLOG_RELCACHESIZE, - &ctl, HASH_ELEM | HASH_FUNCTION); -} - -static void -_xl_remove_hash_entry(XLogRelDesc *rdesc) -{ - Form_pg_class tpgc = rdesc->reldata.rd_rel; - XLogRelCacheEntry *hentry; - - rdesc->lessRecently->moreRecently = rdesc->moreRecently; - rdesc->moreRecently->lessRecently = rdesc->lessRecently; - - hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache, - (void *) &(rdesc->reldata.rd_node), HASH_REMOVE, NULL); - if (hentry == NULL) - elog(PANIC, "_xl_remove_hash_entry: file was not found in cache"); - - RelationCloseSmgr(&(rdesc->reldata)); - - memset(rdesc, 0, sizeof(XLogRelDesc)); - memset(tpgc, 0, sizeof(FormData_pg_class)); - rdesc->reldata.rd_rel = tpgc; -} - -static XLogRelDesc * -_xl_new_reldesc(void) -{ - XLogRelDesc *res; - - _xlast++; - if (_xlast < _xlcnt) - { - _xlrelarr[_xlast].reldata.rd_rel = &(_xlpgcarr[_xlast]); - return &(_xlrelarr[_xlast]); - } - - /* reuse */ - res = _xlrelarr[0].moreRecently; - - _xl_remove_hash_entry(res); - - _xlast--; - return res; -} - - -void -XLogInitRelationCache(void) -{ - _xl_init_rel_cache(); - invalid_page_tab = NULL; -} - -void -XLogCloseRelationCache(void) -{ - HASH_SEQ_STATUS status; - XLogRelCacheEntry *hentry; - - if (!_xlrelarr) - return; - - hash_seq_init(&status, _xlrelcache); - - while ((hentry = (XLogRelCacheEntry *) hash_seq_search(&status)) != NULL) - _xl_remove_hash_entry(hentry->rdesc); - - hash_destroy(_xlrelcache); - - free(_xlrelarr); - free(_xlpgcarr); - - _xlrelarr = NULL; + return rel; } /* - * Open a relation during XLOG replay - * - * Note: this once had an API that allowed NULL return on failure, but it - * no longer does; any failure results in elog(). + * Free a fake relation cache entry. */ -Relation -XLogOpenRelation(RelFileNode rnode) +void +FreeFakeRelcacheEntry(Relation fakerel) { - XLogRelDesc *res; - XLogRelCacheEntry *hentry; - bool found; - - hentry = (XLogRelCacheEntry *) - hash_search(_xlrelcache, (void *) &rnode, HASH_FIND, NULL); - - if (hentry) - { - res = hentry->rdesc; - - res->lessRecently->moreRecently = res->moreRecently; - res->moreRecently->lessRecently = res->lessRecently; - } - else - { - res = _xl_new_reldesc(); - - sprintf(RelationGetRelationName(&(res->reldata)), "%u", rnode.relNode); - - res->reldata.rd_node = rnode; - - /* - * We set up the lockRelId in case anything tries to lock the dummy - * relation. Note that this is fairly bogus since relNode may be - * different from the relation's OID. It shouldn't really matter - * though, since we are presumably running by ourselves and can't have - * any lock conflicts ... - */ - res->reldata.rd_lockInfo.lockRelId.dbId = rnode.dbNode; - res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode; - - hentry = (XLogRelCacheEntry *) - hash_search(_xlrelcache, (void *) &rnode, HASH_ENTER, &found); - - if (found) - elog(PANIC, "xlog relation already present on insert into cache"); - - hentry->rdesc = res; - - res->reldata.rd_targblock = InvalidBlockNumber; - res->reldata.rd_smgr = NULL; - RelationOpenSmgr(&(res->reldata)); - - /* - * Create the target file if it doesn't already exist. This lets us - * cope if the replay sequence contains writes to a relation that is - * later deleted. (The original coding of this routine would instead - * return NULL, causing the writes to be suppressed. But that seems - * like it risks losing valuable data if the filesystem loses an inode - * during a crash. Better to write the data until we are actually - * told to delete the file.) - */ - smgrcreate(res->reldata.rd_smgr, res->reldata.rd_istemp, true); - } - - res->moreRecently = &(_xlrelarr[0]); - res->lessRecently = _xlrelarr[0].lessRecently; - _xlrelarr[0].lessRecently = res; - res->lessRecently->moreRecently = res; - - return &(res->reldata); + pfree(fakerel); } /* * Drop a relation during XLOG replay * - * This is called when the relation is about to be deleted; we need to ensure - * that there is no dangling smgr reference in the xlog relation cache. - * - * Currently, we don't bother to physically remove the relation from the - * cache, we just let it age out normally. - * - * This also takes care of removing any open "invalid-page" records for - * the relation. + * This is called when the relation is about to be deleted; we need to remove + * any open "invalid-page" records for the relation. */ void XLogDropRelation(RelFileNode rnode) { - XLogRelCacheEntry *hentry; - - hentry = (XLogRelCacheEntry *) - hash_search(_xlrelcache, (void *) &rnode, HASH_FIND, NULL); - - if (hentry) - { - XLogRelDesc *rdesc = hentry->rdesc; - - RelationCloseSmgr(&(rdesc->reldata)); - } + /* Tell smgr to forget about this relation as well */ + smgrclosenode(rnode); forget_invalid_pages(rnode, 0); } @@ -507,18 +378,14 @@ XLogDropRelation(RelFileNode rnode) void XLogDropDatabase(Oid dbid) { - HASH_SEQ_STATUS status; - XLogRelCacheEntry *hentry; - - hash_seq_init(&status, _xlrelcache); - - while ((hentry = (XLogRelCacheEntry *) hash_seq_search(&status)) != NULL) - { - XLogRelDesc *rdesc = hentry->rdesc; - - if (hentry->rnode.dbNode == dbid) - RelationCloseSmgr(&(rdesc->reldata)); - } + /* + * This is unnecessarily heavy-handed, as it will close SMgrRelation + * objects for other databases as well. DROP DATABASE occurs seldom + * enough that it's not worth introducing a variant of smgrclose for + * just this purpose. XXX: Or should we rather leave the smgr entries + * dangling? + */ + smgrcloseall(); forget_invalid_pages_db(dbid); } @@ -526,8 +393,7 @@ XLogDropDatabase(Oid dbid) /* * Truncate a relation during XLOG replay * - * We don't need to do anything to the fake relcache, but we do need to - * clean up any open "invalid-page" records for the dropped pages. + * We need to clean up any open "invalid-page" records for the dropped pages. */ void XLogTruncateRelation(RelFileNode rnode, BlockNumber nblocks) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 5d5a3a243c..cdc60db1e5 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.152 2008/05/17 01:20:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.153 2008/06/12 09:12:30 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -1332,7 +1332,6 @@ void seq_redo(XLogRecPtr lsn, XLogRecord *record) { uint8 info = record->xl_info & ~XLR_INFO_MASK; - Relation reln; Buffer buffer; Page page; char *item; @@ -1343,8 +1342,7 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record) if (info != XLOG_SEQ_LOG) elog(PANIC, "seq_redo: unknown op code %u", info); - reln = XLogOpenRelation(xlrec->node); - buffer = XLogReadBuffer(reln, 0, true); + buffer = XLogReadBuffer(xlrec->node, 0, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 7ee888d78d..a474bd1d3e 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.231 2008/06/08 22:00:47 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.232 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -76,9 +76,10 @@ static bool IsForInput; static volatile BufferDesc *PinCountWaitBuf = NULL; -static Buffer ReadBuffer_common(Relation reln, BlockNumber blockNum, - bool zeroPage, - BufferAccessStrategy strategy); +static Buffer ReadBuffer_relcache(Relation reln, BlockNumber blockNum, + bool zeroPage, BufferAccessStrategy strategy); +static Buffer ReadBuffer_common(SMgrRelation reln, bool isLocalBuf, BlockNumber blockNum, + bool zeroPage, BufferAccessStrategy strategy, bool *hit); static bool PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy); static void PinBuffer_Locked(volatile BufferDesc *buf); static void UnpinBuffer(volatile BufferDesc *buf, bool fixOwner); @@ -89,7 +90,7 @@ static bool StartBufferIO(volatile BufferDesc *buf, bool forInput); static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty, int set_flag_bits); static void buffer_write_error_callback(void *arg); -static volatile BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum, +static volatile BufferDesc *BufferAlloc(SMgrRelation smgr, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr); static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln); @@ -114,7 +115,7 @@ static void AtProcExit_Buffers(int code, Datum arg); Buffer ReadBuffer(Relation reln, BlockNumber blockNum) { - return ReadBuffer_common(reln, blockNum, false, NULL); + return ReadBuffer_relcache(reln, blockNum, false, NULL); } /* @@ -125,7 +126,7 @@ Buffer ReadBufferWithStrategy(Relation reln, BlockNumber blockNum, BufferAccessStrategy strategy) { - return ReadBuffer_common(reln, blockNum, false, strategy); + return ReadBuffer_relcache(reln, blockNum, false, strategy); } /* @@ -142,41 +143,79 @@ ReadBufferWithStrategy(Relation reln, BlockNumber blockNum, Buffer ReadOrZeroBuffer(Relation reln, BlockNumber blockNum) { - return ReadBuffer_common(reln, blockNum, true, NULL); + return ReadBuffer_relcache(reln, blockNum, true, NULL); } /* - * ReadBuffer_common -- common logic for ReadBuffer variants + * ReadBufferWithoutRelcache -- like ReadBuffer, but doesn't require a + * relcache entry for the relation. If zeroPage is true, this behaves + * like ReadOrZeroBuffer rather than ReadBuffer. + */ +Buffer +ReadBufferWithoutRelcache(RelFileNode rnode, bool isTemp, + BlockNumber blockNum, bool zeroPage) +{ + bool hit; + + SMgrRelation smgr = smgropen(rnode); + return ReadBuffer_common(smgr, isTemp, blockNum, zeroPage, NULL, &hit); +} + +/* + * ReadBuffer_relcache -- common logic for ReadBuffer-variants that + * operate on a Relation. */ static Buffer -ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, - BufferAccessStrategy strategy) +ReadBuffer_relcache(Relation reln, BlockNumber blockNum, + bool zeroPage, BufferAccessStrategy strategy) +{ + bool hit; + Buffer buf; + + /* Open it at the smgr level if not already done */ + RelationOpenSmgr(reln); + + /* + * Read the buffer, and update pgstat counters to reflect a cache + * hit or miss. + */ + pgstat_count_buffer_read(reln); + buf = ReadBuffer_common(reln->rd_smgr, reln->rd_istemp, blockNum, + zeroPage, strategy, &hit); + if (hit) + pgstat_count_buffer_hit(reln); + return buf; +} + +/* + * ReadBuffer_common -- common logic for all ReadBuffer variants + * + * *hit is set to true if the request was satisfied from shared buffer cache. + */ +static Buffer +ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum, + bool zeroPage, BufferAccessStrategy strategy, bool *hit) { volatile BufferDesc *bufHdr; Block bufBlock; bool found; bool isExtend; - bool isLocalBuf; + + *hit = false; /* Make sure we will have room to remember the buffer pin */ ResourceOwnerEnlargeBuffers(CurrentResourceOwner); isExtend = (blockNum == P_NEW); - isLocalBuf = reln->rd_istemp; - - /* Open it at the smgr level if not already done */ - RelationOpenSmgr(reln); /* Substitute proper block number if caller asked for P_NEW */ if (isExtend) - blockNum = smgrnblocks(reln->rd_smgr); - - pgstat_count_buffer_read(reln); + blockNum = smgrnblocks(smgr); if (isLocalBuf) { ReadLocalBufferCount++; - bufHdr = LocalBufferAlloc(reln, blockNum, &found); + bufHdr = LocalBufferAlloc(smgr, blockNum, &found); if (found) LocalBufferHitCount++; } @@ -188,7 +227,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, * lookup the buffer. IO_IN_PROGRESS is set if the requested block is * not currently in memory. */ - bufHdr = BufferAlloc(reln, blockNum, strategy, &found); + bufHdr = BufferAlloc(smgr, blockNum, strategy, &found); if (found) BufferHitCount++; } @@ -201,7 +240,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, if (!isExtend) { /* Just need to update stats before we exit */ - pgstat_count_buffer_hit(reln); + *hit = true; if (VacuumCostActive) VacuumCostBalance += VacuumCostPageHit; @@ -225,8 +264,8 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr); if (!PageIsNew((PageHeader) bufBlock)) ereport(ERROR, - (errmsg("unexpected data beyond EOF in block %u of relation \"%s\"", - blockNum, RelationGetRelationName(reln)), + (errmsg("unexpected data beyond EOF in block %u of relation %u/%u/%u", + blockNum, smgr->smgr_rnode.spcNode, smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode), errhint("This has been seen to occur with buggy kernels; consider updating your system."))); /* @@ -278,8 +317,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, { /* new buffers are zero-filled */ MemSet((char *) bufBlock, 0, BLCKSZ); - smgrextend(reln->rd_smgr, blockNum, (char *) bufBlock, - reln->rd_istemp); + smgrextend(smgr, blockNum, (char *) bufBlock, isLocalBuf); } else { @@ -290,7 +328,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, if (zeroPage) MemSet((char *) bufBlock, 0, BLCKSZ); else - smgrread(reln->rd_smgr, blockNum, (char *) bufBlock); + smgrread(smgr, blockNum, (char *) bufBlock); /* check for garbage data */ if (!PageHeaderIsValid((PageHeader) bufBlock)) { @@ -298,15 +336,20 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, { ereport(WARNING, (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid page header in block %u of relation \"%s\"; zeroing out page", - blockNum, RelationGetRelationName(reln)))); + errmsg("invalid page header in block %u of relation %u/%u/%u; zeroing out page", + blockNum, + smgr->smgr_rnode.spcNode, + smgr->smgr_rnode.dbNode, + smgr->smgr_rnode.relNode))); MemSet((char *) bufBlock, 0, BLCKSZ); } else ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid page header in block %u of relation \"%s\"", - blockNum, RelationGetRelationName(reln)))); + errmsg("invalid page header in block %u of relation %u/%u/%u", + blockNum, smgr->smgr_rnode.spcNode, + smgr->smgr_rnode.dbNode, + smgr->smgr_rnode.relNode))); } } @@ -347,7 +390,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, * No locks are held either at entry or exit. */ static volatile BufferDesc * -BufferAlloc(Relation reln, +BufferAlloc(SMgrRelation smgr, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr) @@ -364,7 +407,7 @@ BufferAlloc(Relation reln, bool valid; /* create a tag so we can lookup the buffer */ - INIT_BUFFERTAG(newTag, reln, blockNum); + INIT_BUFFERTAG(newTag, smgr->smgr_rnode, blockNum); /* determine its hash code and partition lock ID */ newHash = BufTableHashCode(&newTag); diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index a6f76f5689..ae5f3049a5 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.79 2008/01/01 19:45:51 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.80 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -61,7 +61,7 @@ static Block GetLocalBufferStorage(void); * (hence, usage_count is always advanced). */ BufferDesc * -LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) +LocalBufferAlloc(SMgrRelation smgr, BlockNumber blockNum, bool *foundPtr) { BufferTag newTag; /* identity of requested block */ LocalBufferLookupEnt *hresult; @@ -70,7 +70,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) int trycounter; bool found; - INIT_BUFFERTAG(newTag, reln, blockNum); + INIT_BUFFERTAG(newTag, smgr->smgr_rnode, blockNum); /* Initialize local buffers if first request in this session */ if (LocalBufHash == NULL) @@ -87,7 +87,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) Assert(BUFFERTAGS_EQUAL(bufHdr->tag, newTag)); #ifdef LBDEBUG fprintf(stderr, "LB ALLOC (%u,%d) %d\n", - RelationGetRelid(reln), blockNum, -b - 1); + smgr->smgr_rnode.relNode, blockNum, -b - 1); #endif /* this part is equivalent to PinBuffer for a shared buffer */ if (LocalRefCount[b] == 0) diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index 3f57a2d1b3..d0282f8a6d 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.109 2008/01/01 19:45:52 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.110 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -330,6 +330,13 @@ smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo) xl_smgr_create xlrec; PendingRelDelete *pending; + /* + * Exit quickly in WAL replay mode if we've already opened the file. + * If it's open, it surely must exist. + */ + if (isRedo && reln->md_fd != NULL) + return; + /* * We may be using the target table space for the first time in this * database, so create a per-database subdirectory if needed. diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c index c39ff68fe0..009c6a91bf 100644 --- a/src/backend/utils/init/flatfiles.c +++ b/src/backend/utils/init/flatfiles.c @@ -23,7 +23,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.34 2008/05/12 00:00:52 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.35 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -704,12 +704,6 @@ BuildFlatFiles(bool database_only) rel_authid, rel_authmem; - /* - * We don't have any hope of running a real relcache, but we can use the - * same fake-relcache facility that WAL replay uses. - */ - XLogInitRelationCache(); - /* Need a resowner to keep the heapam and buffer code happy */ owner = ResourceOwnerCreate(NULL, "BuildFlatFiles"); CurrentResourceOwner = owner; @@ -719,9 +713,15 @@ BuildFlatFiles(bool database_only) rnode.dbNode = 0; rnode.relNode = DatabaseRelationId; - /* No locking is needed because no one else is alive yet */ - rel_db = XLogOpenRelation(rnode); + /* + * We don't have any hope of running a real relcache, but we can use the + * same fake-relcache facility that WAL replay uses. + * + * No locking is needed because no one else is alive yet. + */ + rel_db = CreateFakeRelcacheEntry(rnode); write_database_file(rel_db, true); + FreeFakeRelcacheEntry(rel_db); if (!database_only) { @@ -729,21 +729,21 @@ BuildFlatFiles(bool database_only) rnode.spcNode = GLOBALTABLESPACE_OID; rnode.dbNode = 0; rnode.relNode = AuthIdRelationId; - rel_authid = XLogOpenRelation(rnode); + rel_authid = CreateFakeRelcacheEntry(rnode); /* hard-wired path to pg_auth_members */ rnode.spcNode = GLOBALTABLESPACE_OID; rnode.dbNode = 0; rnode.relNode = AuthMemRelationId; - rel_authmem = XLogOpenRelation(rnode); + rel_authmem = CreateFakeRelcacheEntry(rnode); write_auth_file(rel_authid, rel_authmem); + FreeFakeRelcacheEntry(rel_authid); + FreeFakeRelcacheEntry(rel_authmem); } CurrentResourceOwner = NULL; ResourceOwnerDelete(owner); - - XLogCloseRelationCache(); } diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index b34388b4ed..03d201779a 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.29 2008/04/10 22:25:25 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.30 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -284,8 +284,8 @@ extern bool gistfitpage(IndexTuple *itvec, int len); extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace); extern void gistcheckpage(Relation rel, Buffer buf); extern Buffer gistNewBuffer(Relation r); -extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup, - int len, OffsetNumber off); +extern void gistfillbuffer(Page page, IndexTuple *itup, int len, + OffsetNumber off); extern IndexTuple *gistextractpage(Page page, int *len /* out */ ); extern IndexTuple *gistjoinvector( IndexTuple *itvec, int *len, diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 2202690187..17e4a735e9 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.135 2008/06/06 22:35:22 alvherre Exp $ + * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.136 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -124,7 +124,7 @@ extern void heap_page_prune_opt(Relation relation, Buffer buffer, extern int heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin, bool redirect_move, bool report_stats); -extern void heap_page_prune_execute(Relation reln, Buffer buffer, +extern void heap_page_prune_execute(Buffer buffer, OffsetNumber *redirected, int nredirected, OffsetNumber *nowdead, int ndead, OffsetNumber *nowunused, int nunused, diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h index 952c7f22e9..b2d5c3be0f 100644 --- a/src/include/access/xlogutils.h +++ b/src/include/access/xlogutils.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/xlogutils.h,v 1.23 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/xlogutils.h,v 1.24 2008/06/12 09:12:31 heikki Exp $ */ #ifndef XLOG_UTILS_H #define XLOG_UTILS_H @@ -15,15 +15,15 @@ #include "utils/rel.h" -extern void XLogInitRelationCache(void); extern void XLogCheckInvalidPages(void); -extern void XLogCloseRelationCache(void); -extern Relation XLogOpenRelation(RelFileNode rnode); extern void XLogDropRelation(RelFileNode rnode); extern void XLogDropDatabase(Oid dbid); extern void XLogTruncateRelation(RelFileNode rnode, BlockNumber nblocks); -extern Buffer XLogReadBuffer(Relation reln, BlockNumber blkno, bool init); +extern Buffer XLogReadBuffer(RelFileNode rnode, BlockNumber blkno, bool init); + +extern Relation CreateFakeRelcacheEntry(RelFileNode rnode); +extern void FreeFakeRelcacheEntry(Relation fakerel); #endif diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 5178a4d5dc..472e64de1b 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.95 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.96 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "storage/buf.h" #include "storage/lwlock.h" #include "storage/shmem.h" +#include "storage/smgr.h" #include "storage/spin.h" #include "utils/rel.h" @@ -75,9 +76,9 @@ typedef struct buftag (a).blockNum = InvalidBlockNumber \ ) -#define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \ +#define INIT_BUFFERTAG(a,xx_rnode,xx_blockNum) \ ( \ - (a).rnode = (xx_reln)->rd_node, \ + (a).rnode = (xx_rnode), \ (a).blockNum = (xx_blockNum) \ ) @@ -201,7 +202,7 @@ extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id); extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode); /* localbuf.c */ -extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum, +extern BufferDesc *LocalBufferAlloc(SMgrRelation reln, BlockNumber blockNum, bool *foundPtr); extern void MarkLocalBufferDirty(Buffer buffer); extern void DropRelFileNodeLocalBuffers(RelFileNode rnode, diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index d503d56eba..29d8bea287 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.112 2008/06/08 22:00:48 alvherre Exp $ + * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.113 2008/06/12 09:12:31 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -145,6 +145,8 @@ extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum); extern Buffer ReadBufferWithStrategy(Relation reln, BlockNumber blockNum, BufferAccessStrategy strategy); extern Buffer ReadOrZeroBuffer(Relation reln, BlockNumber blockNum); +extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode, bool isTemp, + BlockNumber blockNum, bool zeroPage); extern void ReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer); extern void MarkBufferDirty(Buffer buffer);