Commit a213f1ee authored by Heikki Linnakangas's avatar Heikki Linnakangas

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.
parent c4f2a045
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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" #include "postgres.h"
...@@ -71,12 +71,10 @@ static void ...@@ -71,12 +71,10 @@ static void
ginRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record) ginRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record)
{ {
RelFileNode *node = (RelFileNode *) XLogRecGetData(record); RelFileNode *node = (RelFileNode *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
reln = XLogOpenRelation(*node); buffer = XLogReadBuffer(*node, GIN_ROOT_BLKNO, true);
buffer = XLogReadBuffer(reln, GIN_ROOT_BLKNO, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -94,12 +92,10 @@ ginRedoCreatePTree(XLogRecPtr lsn, XLogRecord *record) ...@@ -94,12 +92,10 @@ ginRedoCreatePTree(XLogRecPtr lsn, XLogRecord *record)
{ {
ginxlogCreatePostingTree *data = (ginxlogCreatePostingTree *) XLogRecGetData(record); ginxlogCreatePostingTree *data = (ginxlogCreatePostingTree *) XLogRecGetData(record);
ItemPointerData *items = (ItemPointerData *) (XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree)); ItemPointerData *items = (ItemPointerData *) (XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree));
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
reln = XLogOpenRelation(data->node); buffer = XLogReadBuffer(data->node, data->blkno, true);
buffer = XLogReadBuffer(reln, data->blkno, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -118,7 +114,6 @@ static void ...@@ -118,7 +114,6 @@ static void
ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) ginRedoInsert(XLogRecPtr lsn, XLogRecord *record)
{ {
ginxlogInsert *data = (ginxlogInsert *) XLogRecGetData(record); ginxlogInsert *data = (ginxlogInsert *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
...@@ -126,8 +121,7 @@ ginRedoInsert(XLogRecPtr lsn, XLogRecord *record) ...@@ -126,8 +121,7 @@ ginRedoInsert(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(data->node); buffer = XLogReadBuffer(data->node, data->blkno, false);
buffer = XLogReadBuffer(reln, data->blkno, false);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -228,26 +222,23 @@ static void ...@@ -228,26 +222,23 @@ static void
ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) ginRedoSplit(XLogRecPtr lsn, XLogRecord *record)
{ {
ginxlogSplit *data = (ginxlogSplit *) XLogRecGetData(record); ginxlogSplit *data = (ginxlogSplit *) XLogRecGetData(record);
Relation reln;
Buffer lbuffer, Buffer lbuffer,
rbuffer; rbuffer;
Page lpage, Page lpage,
rpage; rpage;
uint32 flags = 0; uint32 flags = 0;
reln = XLogOpenRelation(data->node);
if (data->isLeaf) if (data->isLeaf)
flags |= GIN_LEAF; flags |= GIN_LEAF;
if (data->isData) if (data->isData)
flags |= GIN_DATA; flags |= GIN_DATA;
lbuffer = XLogReadBuffer(reln, data->lblkno, data->isRootSplit); lbuffer = XLogReadBuffer(data->node, data->lblkno, data->isRootSplit);
Assert(BufferIsValid(lbuffer)); Assert(BufferIsValid(lbuffer));
lpage = (Page) BufferGetPage(lbuffer); lpage = (Page) BufferGetPage(lbuffer);
GinInitBuffer(lbuffer, flags); GinInitBuffer(lbuffer, flags);
rbuffer = XLogReadBuffer(reln, data->rblkno, true); rbuffer = XLogReadBuffer(data->node, data->rblkno, true);
Assert(BufferIsValid(rbuffer)); Assert(BufferIsValid(rbuffer));
rpage = (Page) BufferGetPage(rbuffer); rpage = (Page) BufferGetPage(rbuffer);
GinInitBuffer(rbuffer, flags); GinInitBuffer(rbuffer, flags);
...@@ -319,7 +310,7 @@ ginRedoSplit(XLogRecPtr lsn, XLogRecord *record) ...@@ -319,7 +310,7 @@ ginRedoSplit(XLogRecPtr lsn, XLogRecord *record)
if (data->isRootSplit) if (data->isRootSplit)
{ {
Buffer rootBuf = XLogReadBuffer(reln, data->rootBlkno, false); Buffer rootBuf = XLogReadBuffer(data->node, data->rootBlkno, false);
Page rootPage = BufferGetPage(rootBuf); Page rootPage = BufferGetPage(rootBuf);
GinInitBuffer(rootBuf, flags & ~GIN_LEAF); GinInitBuffer(rootBuf, flags & ~GIN_LEAF);
...@@ -352,7 +343,6 @@ static void ...@@ -352,7 +343,6 @@ static void
ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record) ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record)
{ {
ginxlogVacuumPage *data = (ginxlogVacuumPage *) XLogRecGetData(record); ginxlogVacuumPage *data = (ginxlogVacuumPage *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
...@@ -360,8 +350,7 @@ ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record) ...@@ -360,8 +350,7 @@ ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(data->node); buffer = XLogReadBuffer(data->node, data->blkno, false);
buffer = XLogReadBuffer(reln, data->blkno, false);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -403,15 +392,12 @@ static void ...@@ -403,15 +392,12 @@ static void
ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record)
{ {
ginxlogDeletePage *data = (ginxlogDeletePage *) XLogRecGetData(record); ginxlogDeletePage *data = (ginxlogDeletePage *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
reln = XLogOpenRelation(data->node);
if (!(record->xl_info & XLR_BKP_BLOCK_1)) if (!(record->xl_info & XLR_BKP_BLOCK_1))
{ {
buffer = XLogReadBuffer(reln, data->blkno, false); buffer = XLogReadBuffer(data->node, data->blkno, false);
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
Assert(GinPageIsData(page)); Assert(GinPageIsData(page));
GinPageGetOpaque(page)->flags = GIN_DELETED; GinPageGetOpaque(page)->flags = GIN_DELETED;
...@@ -423,7 +409,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) ...@@ -423,7 +409,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record)
if (!(record->xl_info & XLR_BKP_BLOCK_2)) if (!(record->xl_info & XLR_BKP_BLOCK_2))
{ {
buffer = XLogReadBuffer(reln, data->parentBlkno, false); buffer = XLogReadBuffer(data->node, data->parentBlkno, false);
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
Assert(GinPageIsData(page)); Assert(GinPageIsData(page));
Assert(!GinPageIsLeaf(page)); Assert(!GinPageIsLeaf(page));
...@@ -436,7 +422,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record) ...@@ -436,7 +422,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record)
if (!(record->xl_info & XLR_BKP_BLOCK_3) && data->leftBlkno != InvalidBlockNumber) 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); page = BufferGetPage(buffer);
Assert(GinPageIsData(page)); Assert(GinPageIsData(page));
GinPageGetOpaque(page)->rightlink = data->rightLink; GinPageGetOpaque(page)->rightlink = data->rightLink;
...@@ -557,9 +543,9 @@ ginContinueSplit(ginIncompleteSplit *split) ...@@ -557,9 +543,9 @@ ginContinueSplit(ginIncompleteSplit *split)
* elog(NOTICE,"ginContinueSplit root:%u l:%u r:%u", split->rootBlkno, * elog(NOTICE,"ginContinueSplit root:%u l:%u r:%u", split->rootBlkno,
* split->leftBlkno, split->rightBlkno); * 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) if (split->rootBlkno == GIN_ROOT_BLKNO)
{ {
...@@ -581,6 +567,8 @@ ginContinueSplit(ginIncompleteSplit *split) ...@@ -581,6 +567,8 @@ ginContinueSplit(ginIncompleteSplit *split)
GinPageGetOpaque(page)->maxoff))->key; GinPageGetOpaque(page)->maxoff))->key;
} }
FreeFakeRelcacheEntry(reln);
btree.rightblkno = split->rightBlkno; btree.rightblkno = split->rightBlkno;
stack.blkno = split->leftBlkno; stack.blkno = split->leftBlkno;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -462,7 +462,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
if (!is_leaf) if (!is_leaf)
PageIndexTupleDelete(state->stack->page, state->stack->childoffnum); 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); MarkBufferDirty(state->stack->buffer);
...@@ -1008,7 +1008,7 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke ...@@ -1008,7 +1008,7 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke
START_CRIT_SECTION(); START_CRIT_SECTION();
GISTInitBuffer(buffer, 0); GISTInitBuffer(buffer, 0);
gistfillbuffer(r, page, itup, len, FirstOffsetNumber); gistfillbuffer(page, itup, len, FirstOffsetNumber);
MarkBufferDirty(buffer); MarkBufferDirty(buffer);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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" #include "postgres.h"
...@@ -27,11 +27,10 @@ static Datum attrS[INDEX_MAX_KEYS]; ...@@ -27,11 +27,10 @@ static Datum attrS[INDEX_MAX_KEYS];
static bool isnullS[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 void
gistfillbuffer(Relation r, Page page, IndexTuple *itup, gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off)
int len, OffsetNumber off)
{ {
OffsetNumber l = InvalidOffsetNumber; OffsetNumber l = InvalidOffsetNumber;
int i; int i;
...@@ -42,14 +41,13 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup, ...@@ -42,14 +41,13 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup,
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
l = PageAddItem(page, (Item) itup[i], IndexTupleSize(itup[i]), Size sz = IndexTupleSize(itup[i]);
off, false, false); l = PageAddItem(page, (Item) itup[i], sz, off, false, false);
if (l == InvalidOffsetNumber) if (l == InvalidOffsetNumber)
elog(ERROR, "failed to add item to index page in \"%s\"", elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes",
RelationGetRelationName(r)); i, len, sz);
off++; off++;
} }
return l;
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -403,7 +403,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
} }
else else
/* enough free space */ /* enough free space */
gistfillbuffer(gv->index, tempPage, addon, curlenaddon, InvalidOffsetNumber); gistfillbuffer(tempPage, addon, curlenaddon, InvalidOffsetNumber);
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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" #include "postgres.h"
...@@ -189,7 +189,6 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) ...@@ -189,7 +189,6 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot)
{ {
gistxlogPageUpdate *xldata = (gistxlogPageUpdate *) XLogRecGetData(record); gistxlogPageUpdate *xldata = (gistxlogPageUpdate *) XLogRecGetData(record);
PageUpdateRecord xlrec; PageUpdateRecord xlrec;
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
...@@ -208,8 +207,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) ...@@ -208,8 +207,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot)
decodePageUpdateRecord(&xlrec, record); decodePageUpdateRecord(&xlrec, record);
reln = XLogOpenRelation(xlrec.data->node); buffer = XLogReadBuffer(xlrec.data->node, xlrec.data->blkno, false);
buffer = XLogReadBuffer(reln, xlrec.data->blkno, false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -234,7 +232,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) ...@@ -234,7 +232,7 @@ gistRedoPageUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot)
/* add tuples */ /* add tuples */
if (xlrec.len > 0) 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 * special case: leafpage, nothing to insert, nothing to delete, then
...@@ -262,7 +260,6 @@ static void ...@@ -262,7 +260,6 @@ static void
gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record) gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record)
{ {
gistxlogPageDelete *xldata = (gistxlogPageDelete *) XLogRecGetData(record); gistxlogPageDelete *xldata = (gistxlogPageDelete *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
...@@ -270,8 +267,7 @@ gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record) ...@@ -270,8 +267,7 @@ gistRedoPageDeleteRecord(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xldata->node); buffer = XLogReadBuffer(xldata->node, xldata->blkno, false);
buffer = XLogReadBuffer(reln, xldata->blkno, false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
...@@ -319,14 +315,12 @@ static void ...@@ -319,14 +315,12 @@ static void
gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record)
{ {
PageSplitRecord xlrec; PageSplitRecord xlrec;
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
int i; int i;
int flags; int flags;
decodePageSplitRecord(&xlrec, record); decodePageSplitRecord(&xlrec, record);
reln = XLogOpenRelation(xlrec.data->node);
flags = xlrec.data->origleaf ? F_LEAF : 0; flags = xlrec.data->origleaf ? F_LEAF : 0;
/* loop around all pages */ /* loop around all pages */
...@@ -334,7 +328,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) ...@@ -334,7 +328,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record)
{ {
NewPage *newpage = xlrec.page + i; NewPage *newpage = xlrec.page + i;
buffer = XLogReadBuffer(reln, newpage->header->blkno, true); buffer = XLogReadBuffer(xlrec.data->node, newpage->header->blkno, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -342,7 +336,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record) ...@@ -342,7 +336,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record)
GISTInitBuffer(buffer, flags); GISTInitBuffer(buffer, flags);
/* and fill it */ /* and fill it */
gistfillbuffer(reln, page, newpage->itup, newpage->header->num, FirstOffsetNumber); gistfillbuffer(page, newpage->itup, newpage->header->num, FirstOffsetNumber);
PageSetLSN(page, lsn); PageSetLSN(page, lsn);
PageSetTLI(page, ThisTimeLineID); PageSetTLI(page, ThisTimeLineID);
...@@ -361,12 +355,10 @@ static void ...@@ -361,12 +355,10 @@ static void
gistRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record) gistRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record)
{ {
RelFileNode *node = (RelFileNode *) XLogRecGetData(record); RelFileNode *node = (RelFileNode *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
reln = XLogOpenRelation(*node); buffer = XLogReadBuffer(*node, GIST_ROOT_BLKNO, true);
buffer = XLogReadBuffer(reln, GIST_ROOT_BLKNO, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -602,7 +594,7 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -602,7 +594,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
lenitup; lenitup;
Relation index; Relation index;
index = XLogOpenRelation(insert->node); index = CreateFakeRelcacheEntry(insert->node);
/* /*
* needed vector itup never will be more than initial lenblkno+2, because * needed vector itup never will be more than initial lenblkno+2, because
...@@ -624,7 +616,7 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -624,7 +616,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
* it was split root, so we should only make new root. it can't be * 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. * 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); gistnewroot(index, buffer, itup, lenitup, NULL);
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
...@@ -703,7 +695,7 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -703,7 +695,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
LockBuffer(buffers[numbuffer], GIST_EXCLUSIVE); LockBuffer(buffers[numbuffer], GIST_EXCLUSIVE);
GISTInitBuffer(buffers[numbuffer], 0); GISTInitBuffer(buffers[numbuffer], 0);
pages[numbuffer] = BufferGetPage(buffers[numbuffer]); pages[numbuffer] = BufferGetPage(buffers[numbuffer]);
gistfillbuffer(index, pages[numbuffer], itup, lenitup, FirstOffsetNumber); gistfillbuffer(pages[numbuffer], itup, lenitup, FirstOffsetNumber);
numbuffer++; numbuffer++;
if (BufferGetBlockNumber(buffers[0]) == GIST_ROOT_BLKNO) if (BufferGetBlockNumber(buffers[0]) == GIST_ROOT_BLKNO)
...@@ -749,7 +741,7 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -749,7 +741,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
for (j = 0; j < ntodelete; j++) for (j = 0; j < ntodelete; j++)
PageIndexTupleDelete(pages[0], todelete[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], rdata = formUpdateRdata(index->rd_node, buffers[0],
todelete, ntodelete, todelete, ntodelete,
...@@ -794,6 +786,8 @@ gistContinueInsert(gistIncompleteInsert *insert) ...@@ -794,6 +786,8 @@ gistContinueInsert(gistIncompleteInsert *insert)
} }
} }
FreeFakeRelcacheEntry(index);
ereport(LOG, ereport(LOG,
(errmsg("index %u/%u/%u needs VACUUM FULL or REINDEX to finish crash recovery", (errmsg("index %u/%u/%u needs VACUUM FULL or REINDEX to finish crash recovery",
insert->node.spcNode, insert->node.dbNode, insert->node.relNode), insert->node.spcNode, insert->node.dbNode, insert->node.relNode),
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -3944,7 +3944,6 @@ static void ...@@ -3944,7 +3944,6 @@ static void
heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move)
{ {
xl_heap_clean *xlrec = (xl_heap_clean *) XLogRecGetData(record); xl_heap_clean *xlrec = (xl_heap_clean *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber *end; OffsetNumber *end;
...@@ -3958,8 +3957,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) ...@@ -3958,8 +3957,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, xlrec->block, false);
buffer = XLogReadBuffer(reln, xlrec->block, false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -3980,7 +3978,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move) ...@@ -3980,7 +3978,7 @@ heap_xlog_clean(XLogRecPtr lsn, XLogRecord *record, bool clean_move)
Assert(nunused >= 0); Assert(nunused >= 0);
/* Update all item pointers per the record, and repair fragmentation */ /* Update all item pointers per the record, and repair fragmentation */
heap_page_prune_execute(reln, buffer, heap_page_prune_execute(buffer,
redirected, nredirected, redirected, nredirected,
nowdead, ndead, nowdead, ndead,
nowunused, nunused, nowunused, nunused,
...@@ -4002,15 +4000,13 @@ heap_xlog_freeze(XLogRecPtr lsn, XLogRecord *record) ...@@ -4002,15 +4000,13 @@ heap_xlog_freeze(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record); xl_heap_freeze *xlrec = (xl_heap_freeze *) XLogRecGetData(record);
TransactionId cutoff_xid = xlrec->cutoff_xid; TransactionId cutoff_xid = xlrec->cutoff_xid;
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, xlrec->block, false);
buffer = XLogReadBuffer(reln, xlrec->block, false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -4050,7 +4046,6 @@ static void ...@@ -4050,7 +4046,6 @@ static void
heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record) heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_newpage *xlrec = (xl_heap_newpage *) XLogRecGetData(record); xl_heap_newpage *xlrec = (xl_heap_newpage *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
...@@ -4058,8 +4053,7 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record) ...@@ -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 * Note: the NEWPAGE log record is used for both heaps and indexes, so do
* not do anything that assumes we are touching a heap. * not do anything that assumes we are touching a heap.
*/ */
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, xlrec->blkno, true);
buffer = XLogReadBuffer(reln, xlrec->blkno, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -4076,7 +4070,6 @@ static void ...@@ -4076,7 +4070,6 @@ static void
heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record) heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
...@@ -4086,8 +4079,7 @@ heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record) ...@@ -4086,8 +4079,7 @@ heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xlrec->target.node); buffer = XLogReadBuffer(xlrec->target.node,
buffer = XLogReadBuffer(reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
...@@ -4133,7 +4125,6 @@ static void ...@@ -4133,7 +4125,6 @@ static void
heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
...@@ -4149,11 +4140,9 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) ...@@ -4149,11 +4140,9 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xlrec->target.node);
if (record->xl_info & XLOG_HEAP_INIT_PAGE) if (record->xl_info & XLOG_HEAP_INIT_PAGE)
{ {
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
true); true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
...@@ -4163,7 +4152,7 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record) ...@@ -4163,7 +4152,7 @@ heap_xlog_insert(XLogRecPtr lsn, XLogRecord *record)
} }
else else
{ {
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
...@@ -4216,7 +4205,6 @@ static void ...@@ -4216,7 +4205,6 @@ static void
heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update) heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update)
{ {
xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record);
Relation reln = XLogOpenRelation(xlrec->target.node);
Buffer buffer; Buffer buffer;
bool samepage = (ItemPointerGetBlockNumber(&(xlrec->newtid)) == bool samepage = (ItemPointerGetBlockNumber(&(xlrec->newtid)) ==
ItemPointerGetBlockNumber(&(xlrec->target.tid))); ItemPointerGetBlockNumber(&(xlrec->target.tid)));
...@@ -4242,7 +4230,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update) ...@@ -4242,7 +4230,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update)
/* Deal with old tuple version */ /* Deal with old tuple version */
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
...@@ -4317,7 +4305,7 @@ newt:; ...@@ -4317,7 +4305,7 @@ newt:;
if (record->xl_info & XLOG_HEAP_INIT_PAGE) if (record->xl_info & XLOG_HEAP_INIT_PAGE)
{ {
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->newtid)), ItemPointerGetBlockNumber(&(xlrec->newtid)),
true); true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
...@@ -4327,7 +4315,7 @@ newt:; ...@@ -4327,7 +4315,7 @@ newt:;
} }
else else
{ {
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->newtid)), ItemPointerGetBlockNumber(&(xlrec->newtid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
...@@ -4399,7 +4387,6 @@ static void ...@@ -4399,7 +4387,6 @@ static void
heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record) heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
...@@ -4409,8 +4396,7 @@ heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record) ...@@ -4409,8 +4396,7 @@ heap_xlog_lock(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
reln = XLogOpenRelation(xlrec->target.node); buffer = XLogReadBuffer(xlrec->target.node,
buffer = XLogReadBuffer(reln,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
...@@ -4458,7 +4444,6 @@ static void ...@@ -4458,7 +4444,6 @@ static void
heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record) heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record);
Relation reln = XLogOpenRelation(xlrec->target.node);
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
...@@ -4470,7 +4455,7 @@ heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record) ...@@ -4470,7 +4455,7 @@ heap_xlog_inplace(XLogRecPtr lsn, XLogRecord *record)
if (record->xl_info & XLR_BKP_BLOCK_1) if (record->xl_info & XLR_BKP_BLOCK_1)
return; return;
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -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 * and update the page's hint bit about whether it has free line
* pointers. * pointers.
*/ */
heap_page_prune_execute(relation, buffer, heap_page_prune_execute(buffer,
prstate.redirected, prstate.nredirected, prstate.redirected, prstate.nredirected,
prstate.nowdead, prstate.ndead, prstate.nowdead, prstate.ndead,
prstate.nowunused, prstate.nunused, prstate.nowunused, prstate.nunused,
...@@ -696,7 +696,7 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum) ...@@ -696,7 +696,7 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum)
* arguments are identical to those of log_heap_clean(). * arguments are identical to those of log_heap_clean().
*/ */
void void
heap_page_prune_execute(Relation reln, Buffer buffer, heap_page_prune_execute(Buffer buffer,
OffsetNumber *redirected, int nredirected, OffsetNumber *redirected, int nredirected,
OffsetNumber *nowdead, int ndead, OffsetNumber *nowdead, int ndead,
OffsetNumber *nowunused, int nunused, OffsetNumber *nowunused, int nunused,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -150,7 +150,7 @@ _bt_restore_page(Page page, char *from, int len)
} }
static void static void
_bt_restore_meta(Relation reln, XLogRecPtr lsn, _bt_restore_meta(RelFileNode rnode, XLogRecPtr lsn,
BlockNumber root, uint32 level, BlockNumber root, uint32 level,
BlockNumber fastroot, uint32 fastlevel) BlockNumber fastroot, uint32 fastlevel)
{ {
...@@ -159,7 +159,7 @@ _bt_restore_meta(Relation reln, XLogRecPtr lsn, ...@@ -159,7 +159,7 @@ _bt_restore_meta(Relation reln, XLogRecPtr lsn,
BTMetaPageData *md; BTMetaPageData *md;
BTPageOpaque pageop; BTPageOpaque pageop;
metabuf = XLogReadBuffer(reln, BTREE_METAPAGE, true); metabuf = XLogReadBuffer(rnode, BTREE_METAPAGE, true);
Assert(BufferIsValid(metabuf)); Assert(BufferIsValid(metabuf));
metapg = BufferGetPage(metabuf); metapg = BufferGetPage(metabuf);
...@@ -194,7 +194,6 @@ btree_xlog_insert(bool isleaf, bool ismeta, ...@@ -194,7 +194,6 @@ btree_xlog_insert(bool isleaf, bool ismeta,
XLogRecPtr lsn, XLogRecord *record) XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_insert *xlrec = (xl_btree_insert *) XLogRecGetData(record); xl_btree_insert *xlrec = (xl_btree_insert *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
char *datapos; char *datapos;
...@@ -220,11 +219,9 @@ btree_xlog_insert(bool isleaf, bool ismeta, ...@@ -220,11 +219,9 @@ btree_xlog_insert(bool isleaf, bool ismeta,
if ((record->xl_info & XLR_BKP_BLOCK_1) && !ismeta && isleaf) if ((record->xl_info & XLR_BKP_BLOCK_1) && !ismeta && isleaf)
return; /* nothing to do */ return; /* nothing to do */
reln = XLogOpenRelation(xlrec->target.node);
if (!(record->xl_info & XLR_BKP_BLOCK_1)) if (!(record->xl_info & XLR_BKP_BLOCK_1))
{ {
buffer = XLogReadBuffer(reln, buffer = XLogReadBuffer(xlrec->target.node,
ItemPointerGetBlockNumber(&(xlrec->target.tid)), ItemPointerGetBlockNumber(&(xlrec->target.tid)),
false); false);
if (BufferIsValid(buffer)) if (BufferIsValid(buffer))
...@@ -251,7 +248,7 @@ btree_xlog_insert(bool isleaf, bool ismeta, ...@@ -251,7 +248,7 @@ btree_xlog_insert(bool isleaf, bool ismeta,
} }
if (ismeta) if (ismeta)
_bt_restore_meta(reln, lsn, _bt_restore_meta(xlrec->target.node, lsn,
md.root, md.level, md.root, md.level,
md.fastroot, md.fastlevel); md.fastroot, md.fastlevel);
...@@ -265,7 +262,6 @@ btree_xlog_split(bool onleft, bool isroot, ...@@ -265,7 +262,6 @@ btree_xlog_split(bool onleft, bool isroot,
XLogRecPtr lsn, XLogRecord *record) XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record); xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record);
Relation reln;
Buffer rbuf; Buffer rbuf;
Page rpage; Page rpage;
BTPageOpaque ropaque; BTPageOpaque ropaque;
...@@ -277,8 +273,6 @@ btree_xlog_split(bool onleft, bool isroot, ...@@ -277,8 +273,6 @@ btree_xlog_split(bool onleft, bool isroot,
Item left_hikey = NULL; Item left_hikey = NULL;
Size left_hikeysz = 0; Size left_hikeysz = 0;
reln = XLogOpenRelation(xlrec->node);
datapos = (char *) xlrec + SizeOfBtreeSplit; datapos = (char *) xlrec + SizeOfBtreeSplit;
datalen = record->xl_len - SizeOfBtreeSplit; datalen = record->xl_len - SizeOfBtreeSplit;
...@@ -328,7 +322,7 @@ btree_xlog_split(bool onleft, bool isroot, ...@@ -328,7 +322,7 @@ btree_xlog_split(bool onleft, bool isroot,
} }
/* Reconstruct right (new) sibling from scratch */ /* Reconstruct right (new) sibling from scratch */
rbuf = XLogReadBuffer(reln, xlrec->rightsib, true); rbuf = XLogReadBuffer(xlrec->node, xlrec->rightsib, true);
Assert(BufferIsValid(rbuf)); Assert(BufferIsValid(rbuf));
rpage = (Page) BufferGetPage(rbuf); rpage = (Page) BufferGetPage(rbuf);
...@@ -369,7 +363,7 @@ btree_xlog_split(bool onleft, bool isroot, ...@@ -369,7 +363,7 @@ btree_xlog_split(bool onleft, bool isroot,
*/ */
if (!(record->xl_info & XLR_BKP_BLOCK_1)) 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)) if (BufferIsValid(lbuf))
{ {
...@@ -439,7 +433,7 @@ btree_xlog_split(bool onleft, bool isroot, ...@@ -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 */ /* 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)) 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)) if (BufferIsValid(buffer))
{ {
...@@ -468,7 +462,6 @@ static void ...@@ -468,7 +462,6 @@ static void
btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record) btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_delete *xlrec; xl_btree_delete *xlrec;
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
BTPageOpaque opaque; BTPageOpaque opaque;
...@@ -477,8 +470,7 @@ btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record) ...@@ -477,8 +470,7 @@ btree_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
return; return;
xlrec = (xl_btree_delete *) XLogRecGetData(record); xlrec = (xl_btree_delete *) XLogRecGetData(record);
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, xlrec->block, false);
buffer = XLogReadBuffer(reln, xlrec->block, false);
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
return; return;
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -517,7 +509,6 @@ static void ...@@ -517,7 +509,6 @@ static void
btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_delete_page *xlrec = (xl_btree_delete_page *) XLogRecGetData(record); xl_btree_delete_page *xlrec = (xl_btree_delete_page *) XLogRecGetData(record);
Relation reln;
BlockNumber parent; BlockNumber parent;
BlockNumber target; BlockNumber target;
BlockNumber leftsib; BlockNumber leftsib;
...@@ -526,7 +517,6 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -526,7 +517,6 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
Page page; Page page;
BTPageOpaque pageop; BTPageOpaque pageop;
reln = XLogOpenRelation(xlrec->target.node);
parent = ItemPointerGetBlockNumber(&(xlrec->target.tid)); parent = ItemPointerGetBlockNumber(&(xlrec->target.tid));
target = xlrec->deadblk; target = xlrec->deadblk;
leftsib = xlrec->leftblk; leftsib = xlrec->leftblk;
...@@ -535,7 +525,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -535,7 +525,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
/* parent page */ /* parent page */
if (!(record->xl_info & XLR_BKP_BLOCK_1)) if (!(record->xl_info & XLR_BKP_BLOCK_1))
{ {
buffer = XLogReadBuffer(reln, parent, false); buffer = XLogReadBuffer(xlrec->target.node, parent, false);
if (BufferIsValid(buffer)) if (BufferIsValid(buffer))
{ {
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -581,7 +571,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -581,7 +571,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
/* Fix left-link of right sibling */ /* Fix left-link of right sibling */
if (!(record->xl_info & XLR_BKP_BLOCK_2)) if (!(record->xl_info & XLR_BKP_BLOCK_2))
{ {
buffer = XLogReadBuffer(reln, rightsib, false); buffer = XLogReadBuffer(xlrec->target.node, rightsib, false);
if (BufferIsValid(buffer)) if (BufferIsValid(buffer))
{ {
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -607,7 +597,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -607,7 +597,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
{ {
if (leftsib != P_NONE) if (leftsib != P_NONE)
{ {
buffer = XLogReadBuffer(reln, leftsib, false); buffer = XLogReadBuffer(xlrec->target.node, leftsib, false);
if (BufferIsValid(buffer)) if (BufferIsValid(buffer))
{ {
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -630,7 +620,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -630,7 +620,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
} }
/* Rewrite target page as empty deleted page */ /* Rewrite target page as empty deleted page */
buffer = XLogReadBuffer(reln, target, true); buffer = XLogReadBuffer(xlrec->target.node, target, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -655,7 +645,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record) ...@@ -655,7 +645,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
memcpy(&md, (char *) xlrec + SizeOfBtreeDeletePage, memcpy(&md, (char *) xlrec + SizeOfBtreeDeletePage,
sizeof(xl_btree_metadata)); sizeof(xl_btree_metadata));
_bt_restore_meta(reln, lsn, _bt_restore_meta(xlrec->target.node, lsn,
md.root, md.level, md.root, md.level,
md.fastroot, md.fastlevel); md.fastroot, md.fastlevel);
} }
...@@ -672,14 +662,12 @@ static void ...@@ -672,14 +662,12 @@ static void
btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record) btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record)
{ {
xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record); xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record);
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
BTPageOpaque pageop; BTPageOpaque pageop;
BlockNumber downlink = 0; BlockNumber downlink = 0;
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, xlrec->rootblk, true);
buffer = XLogReadBuffer(reln, xlrec->rootblk, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -711,7 +699,7 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record) ...@@ -711,7 +699,7 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record)
MarkBufferDirty(buffer); MarkBufferDirty(buffer);
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
_bt_restore_meta(reln, lsn, _bt_restore_meta(xlrec->node, lsn,
xlrec->rootblk, xlrec->level, xlrec->rootblk, xlrec->level,
xlrec->rootblk, xlrec->level); xlrec->rootblk, xlrec->level);
...@@ -904,9 +892,7 @@ btree_xlog_cleanup(void) ...@@ -904,9 +892,7 @@ btree_xlog_cleanup(void)
foreach(l, incomplete_actions) foreach(l, incomplete_actions)
{ {
bt_incomplete_action *action = (bt_incomplete_action *) lfirst(l); bt_incomplete_action *action = (bt_incomplete_action *) lfirst(l);
Relation reln;
reln = XLogOpenRelation(action->node);
if (action->is_split) if (action->is_split)
{ {
/* finish an incomplete split */ /* finish an incomplete split */
...@@ -917,14 +903,15 @@ btree_xlog_cleanup(void) ...@@ -917,14 +903,15 @@ btree_xlog_cleanup(void)
BTPageOpaque lpageop, BTPageOpaque lpageop,
rpageop; rpageop;
bool is_only; 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 */ /* failure is impossible because we wrote this page earlier */
if (!BufferIsValid(lbuf)) if (!BufferIsValid(lbuf))
elog(PANIC, "btree_xlog_cleanup: left block unfound"); elog(PANIC, "btree_xlog_cleanup: left block unfound");
lpage = (Page) BufferGetPage(lbuf); lpage = (Page) BufferGetPage(lbuf);
lpageop = (BTPageOpaque) PageGetSpecialPointer(lpage); 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 */ /* failure is impossible because we wrote this page earlier */
if (!BufferIsValid(rbuf)) if (!BufferIsValid(rbuf))
elog(PANIC, "btree_xlog_cleanup: right block unfound"); elog(PANIC, "btree_xlog_cleanup: right block unfound");
...@@ -934,18 +921,26 @@ btree_xlog_cleanup(void) ...@@ -934,18 +921,26 @@ btree_xlog_cleanup(void)
/* if the pages are all of their level, it's a only-page split */ /* if the pages are all of their level, it's a only-page split */
is_only = P_LEFTMOST(lpageop) && P_RIGHTMOST(rpageop); is_only = P_LEFTMOST(lpageop) && P_RIGHTMOST(rpageop);
reln = CreateFakeRelcacheEntry(action->node);
_bt_insert_parent(reln, lbuf, rbuf, NULL, _bt_insert_parent(reln, lbuf, rbuf, NULL,
action->is_root, is_only); action->is_root, is_only);
FreeFakeRelcacheEntry(reln);
} }
else else
{ {
/* finish an incomplete deletion (of a half-dead page) */ /* finish an incomplete deletion (of a half-dead page) */
Buffer buf; Buffer buf;
buf = XLogReadBuffer(reln, action->delblk, false); buf = XLogReadBuffer(action->node, action->delblk, false);
if (BufferIsValid(buf)) if (BufferIsValid(buf))
{
Relation reln;
reln = CreateFakeRelcacheEntry(action->node);
if (_bt_pagedel(reln, buf, NULL, true) == 0) if (_bt_pagedel(reln, buf, NULL, true) == 0)
elog(PANIC, "btree_xlog_cleanup: _bt_pagdel failed"); elog(PANIC, "btree_xlog_cleanup: _bt_pagdel failed");
FreeFakeRelcacheEntry(reln);
}
} }
} }
incomplete_actions = NIL; incomplete_actions = NIL;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -2840,7 +2840,6 @@ CleanupBackupHistory(void)
static void static void
RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn) RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn)
{ {
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
BkpBlock bkpb; BkpBlock bkpb;
...@@ -2856,8 +2855,7 @@ RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn) ...@@ -2856,8 +2855,7 @@ RestoreBkpBlocks(XLogRecord *record, XLogRecPtr lsn)
memcpy(&bkpb, blk, sizeof(BkpBlock)); memcpy(&bkpb, blk, sizeof(BkpBlock));
blk += sizeof(BkpBlock); blk += sizeof(BkpBlock);
reln = XLogOpenRelation(bkpb.node); buffer = XLogReadBuffer(bkpb.node, bkpb.block, true);
buffer = XLogReadBuffer(reln, bkpb.block, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
...@@ -5064,9 +5062,7 @@ StartupXLOG(void) ...@@ -5064,9 +5062,7 @@ StartupXLOG(void)
BACKUP_LABEL_FILE, BACKUP_LABEL_OLD))); BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
} }
/* Start up the recovery environment */ /* Initialize resource managers */
XLogInitRelationCache();
for (rmid = 0; rmid <= RM_MAX_ID; rmid++) for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
{ {
if (RmgrTable[rmid].rm_startup != NULL) if (RmgrTable[rmid].rm_startup != NULL)
...@@ -5330,11 +5326,6 @@ StartupXLOG(void) ...@@ -5330,11 +5326,6 @@ StartupXLOG(void)
* allows some extra error checking in xlog_redo. * allows some extra error checking in xlog_redo.
*/ */
CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
/*
* Close down recovery environment
*/
XLogCloseRelationCache();
} }
/* /*
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -190,6 +190,9 @@ XLogCheckInvalidPages(void)
if (foundone) if (foundone)
elog(PANIC, "WAL contains references to invalid pages"); elog(PANIC, "WAL contains references to invalid pages");
hash_destroy(invalid_page_tab);
invalid_page_tab = NULL;
} }
...@@ -218,27 +221,40 @@ XLogCheckInvalidPages(void) ...@@ -218,27 +221,40 @@ XLogCheckInvalidPages(void)
* at the end of WAL replay.) * at the end of WAL replay.)
*/ */
Buffer Buffer
XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) XLogReadBuffer(RelFileNode rnode, BlockNumber blkno, bool init)
{ {
BlockNumber lastblock = RelationGetNumberOfBlocks(reln); BlockNumber lastblock;
Buffer buffer; Buffer buffer;
SMgrRelation smgr;
Assert(blkno != P_NEW); 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) if (blkno < lastblock)
{ {
/* page exists in file */ /* page exists in file */
if (init) buffer = ReadBufferWithoutRelcache(rnode, false, blkno, init);
buffer = ReadOrZeroBuffer(reln, blkno);
else
buffer = ReadBuffer(reln, blkno);
} }
else else
{ {
/* hm, page doesn't exist in file */ /* hm, page doesn't exist in file */
if (!init) if (!init)
{ {
log_invalid_page(reln->rd_node, blkno, false); log_invalid_page(rnode, blkno, false);
return InvalidBuffer; return InvalidBuffer;
} }
/* OK to extend the file */ /* OK to extend the file */
...@@ -249,7 +265,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) ...@@ -249,7 +265,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init)
{ {
if (buffer != InvalidBuffer) if (buffer != InvalidBuffer)
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
buffer = ReadBuffer(reln, P_NEW); buffer = ReadBufferWithoutRelcache(rnode, false, P_NEW, false);
lastblock++; lastblock++;
} }
Assert(BufferGetBlockNumber(buffer) == blkno); Assert(BufferGetBlockNumber(buffer) == blkno);
...@@ -265,7 +281,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) ...@@ -265,7 +281,7 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init)
if (PageIsNew((PageHeader) page)) if (PageIsNew((PageHeader) page))
{ {
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
log_invalid_page(reln->rd_node, blkno, true); log_invalid_page(rnode, blkno, true);
return InvalidBuffer; return InvalidBuffer;
} }
} }
...@@ -275,226 +291,81 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init) ...@@ -275,226 +291,81 @@ XLogReadBuffer(Relation reln, BlockNumber blkno, bool init)
/* /*
* Lightweight "Relation" cache --- this substitutes for the normal relcache * Struct actually returned by XLogFakeRelcacheEntry, though the declared
* during XLOG replay. * return type is Relation.
*/ */
typedef struct
typedef struct XLogRelDesc
{
RelationData reldata;
struct XLogRelDesc *lessRecently;
struct XLogRelDesc *moreRecently;
} XLogRelDesc;
typedef struct XLogRelCacheEntry
{ {
RelFileNode rnode; RelationData reldata; /* Note: this must be first */
XLogRelDesc *rdesc; FormData_pg_class pgc;
} XLogRelCacheEntry; } FakeRelCacheEntryData;
static HTAB *_xlrelcache; typedef FakeRelCacheEntryData *FakeRelCacheEntry;
static XLogRelDesc *_xlrelarr = NULL;
static Form_pg_class _xlpgcarr = NULL;
static int _xlast = 0;
static int _xlcnt = 0;
#define _XLOG_RELCACHESIZE 512 /*
* Create a fake relation cache entry for a physical relation
static void *
_xl_init_rel_cache(void) * 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.
HASHCTL ctl; * 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
_xlcnt = _XLOG_RELCACHESIZE; * fields related to physical storage, like rd_rel, are initialized, so the
_xlast = 0; * fake entry is only usable in low-level operations like ReadBuffer().
_xlrelarr = (XLogRelDesc *) malloc(sizeof(XLogRelDesc) * _xlcnt); *
memset(_xlrelarr, 0, sizeof(XLogRelDesc) * _xlcnt); * Caller must free the returned entry with FreeFakeRelcacheEntry().
_xlpgcarr = (Form_pg_class) malloc(sizeof(FormData_pg_class) * _xlcnt); */
memset(_xlpgcarr, 0, sizeof(FormData_pg_class) * _xlcnt); Relation
CreateFakeRelcacheEntry(RelFileNode rnode)
_xlrelarr[0].moreRecently = &(_xlrelarr[0]);
_xlrelarr[0].lessRecently = &(_xlrelarr[0]);
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; FakeRelCacheEntry fakeentry;
XLogRelCacheEntry *hentry; Relation rel;
if (!_xlrelarr) /* Allocate the Relation struct and all related space in one block. */
return; fakeentry = palloc0(sizeof(FakeRelCacheEntryData));
rel = (Relation) fakeentry;
hash_seq_init(&status, _xlrelcache); rel->rd_rel = &fakeentry->pgc;
rel->rd_node = rnode;
while ((hentry = (XLogRelCacheEntry *) hash_seq_search(&status)) != NULL) /* We don't know the name of the relation; use relfilenode instead */
_xl_remove_hash_entry(hentry->rdesc); sprintf(RelationGetRelationName(rel), "%u", rnode.relNode);
hash_destroy(_xlrelcache); /*
* 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;
free(_xlrelarr); rel->rd_targblock = InvalidBlockNumber;
free(_xlpgcarr); rel->rd_smgr = NULL;
_xlrelarr = NULL; return rel;
} }
/* /*
* Open a relation during XLOG replay * Free a fake relation cache entry.
*
* Note: this once had an API that allowed NULL return on failure, but it
* no longer does; any failure results in elog().
*/ */
Relation void
XLogOpenRelation(RelFileNode rnode) FreeFakeRelcacheEntry(Relation fakerel)
{ {
XLogRelDesc *res; pfree(fakerel);
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);
} }
/* /*
* Drop a relation during XLOG replay * Drop a relation during XLOG replay
* *
* This is called when the relation is about to be deleted; we need to ensure * This is called when the relation is about to be deleted; we need to remove
* that there is no dangling smgr reference in the xlog relation cache. * any open "invalid-page" records for the relation.
*
* 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.
*/ */
void void
XLogDropRelation(RelFileNode rnode) XLogDropRelation(RelFileNode rnode)
{ {
XLogRelCacheEntry *hentry; /* Tell smgr to forget about this relation as well */
smgrclosenode(rnode);
hentry = (XLogRelCacheEntry *)
hash_search(_xlrelcache, (void *) &rnode, HASH_FIND, NULL);
if (hentry)
{
XLogRelDesc *rdesc = hentry->rdesc;
RelationCloseSmgr(&(rdesc->reldata));
}
forget_invalid_pages(rnode, 0); forget_invalid_pages(rnode, 0);
} }
...@@ -507,18 +378,14 @@ XLogDropRelation(RelFileNode rnode) ...@@ -507,18 +378,14 @@ XLogDropRelation(RelFileNode rnode)
void void
XLogDropDatabase(Oid dbid) XLogDropDatabase(Oid dbid)
{ {
HASH_SEQ_STATUS status; /*
XLogRelCacheEntry *hentry; * This is unnecessarily heavy-handed, as it will close SMgrRelation
* objects for other databases as well. DROP DATABASE occurs seldom
hash_seq_init(&status, _xlrelcache); * enough that it's not worth introducing a variant of smgrclose for
* just this purpose. XXX: Or should we rather leave the smgr entries
while ((hentry = (XLogRelCacheEntry *) hash_seq_search(&status)) != NULL) * dangling?
{ */
XLogRelDesc *rdesc = hentry->rdesc; smgrcloseall();
if (hentry->rnode.dbNode == dbid)
RelationCloseSmgr(&(rdesc->reldata));
}
forget_invalid_pages_db(dbid); forget_invalid_pages_db(dbid);
} }
...@@ -526,8 +393,7 @@ XLogDropDatabase(Oid dbid) ...@@ -526,8 +393,7 @@ XLogDropDatabase(Oid dbid)
/* /*
* Truncate a relation during XLOG replay * Truncate a relation during XLOG replay
* *
* We don't need to do anything to the fake relcache, but we do need to * We need to clean up any open "invalid-page" records for the dropped pages.
* clean up any open "invalid-page" records for the dropped pages.
*/ */
void void
XLogTruncateRelation(RelFileNode rnode, BlockNumber nblocks) XLogTruncateRelation(RelFileNode rnode, BlockNumber nblocks)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 ...@@ -1332,7 +1332,6 @@ void
seq_redo(XLogRecPtr lsn, XLogRecord *record) seq_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
uint8 info = record->xl_info & ~XLR_INFO_MASK; uint8 info = record->xl_info & ~XLR_INFO_MASK;
Relation reln;
Buffer buffer; Buffer buffer;
Page page; Page page;
char *item; char *item;
...@@ -1343,8 +1342,7 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -1343,8 +1342,7 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
if (info != XLOG_SEQ_LOG) if (info != XLOG_SEQ_LOG)
elog(PANIC, "seq_redo: unknown op code %u", info); elog(PANIC, "seq_redo: unknown op code %u", info);
reln = XLogOpenRelation(xlrec->node); buffer = XLogReadBuffer(xlrec->node, 0, true);
buffer = XLogReadBuffer(reln, 0, true);
Assert(BufferIsValid(buffer)); Assert(BufferIsValid(buffer));
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; ...@@ -76,9 +76,10 @@ static bool IsForInput;
static volatile BufferDesc *PinCountWaitBuf = NULL; static volatile BufferDesc *PinCountWaitBuf = NULL;
static Buffer ReadBuffer_common(Relation reln, BlockNumber blockNum, static Buffer ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
bool zeroPage, bool zeroPage, BufferAccessStrategy strategy);
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 bool PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy);
static void PinBuffer_Locked(volatile BufferDesc *buf); static void PinBuffer_Locked(volatile BufferDesc *buf);
static void UnpinBuffer(volatile BufferDesc *buf, bool fixOwner); static void UnpinBuffer(volatile BufferDesc *buf, bool fixOwner);
...@@ -89,7 +90,7 @@ static bool StartBufferIO(volatile BufferDesc *buf, bool forInput); ...@@ -89,7 +90,7 @@ static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty, static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,
int set_flag_bits); int set_flag_bits);
static void buffer_write_error_callback(void *arg); 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, BufferAccessStrategy strategy,
bool *foundPtr); bool *foundPtr);
static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln); static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln);
...@@ -114,7 +115,7 @@ static void AtProcExit_Buffers(int code, Datum arg); ...@@ -114,7 +115,7 @@ static void AtProcExit_Buffers(int code, Datum arg);
Buffer Buffer
ReadBuffer(Relation reln, BlockNumber blockNum) ReadBuffer(Relation reln, BlockNumber blockNum)
{ {
return ReadBuffer_common(reln, blockNum, false, NULL); return ReadBuffer_relcache(reln, blockNum, false, NULL);
} }
/* /*
...@@ -125,7 +126,7 @@ Buffer ...@@ -125,7 +126,7 @@ Buffer
ReadBufferWithStrategy(Relation reln, BlockNumber blockNum, ReadBufferWithStrategy(Relation reln, BlockNumber blockNum,
BufferAccessStrategy strategy) 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, ...@@ -142,41 +143,79 @@ ReadBufferWithStrategy(Relation reln, BlockNumber blockNum,
Buffer Buffer
ReadOrZeroBuffer(Relation reln, BlockNumber blockNum) 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_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 static Buffer
ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
BufferAccessStrategy strategy) bool zeroPage, BufferAccessStrategy strategy, bool *hit)
{ {
volatile BufferDesc *bufHdr; volatile BufferDesc *bufHdr;
Block bufBlock; Block bufBlock;
bool found; bool found;
bool isExtend; bool isExtend;
bool isLocalBuf;
*hit = false;
/* Make sure we will have room to remember the buffer pin */ /* Make sure we will have room to remember the buffer pin */
ResourceOwnerEnlargeBuffers(CurrentResourceOwner); ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
isExtend = (blockNum == P_NEW); 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 */ /* Substitute proper block number if caller asked for P_NEW */
if (isExtend) if (isExtend)
blockNum = smgrnblocks(reln->rd_smgr); blockNum = smgrnblocks(smgr);
pgstat_count_buffer_read(reln);
if (isLocalBuf) if (isLocalBuf)
{ {
ReadLocalBufferCount++; ReadLocalBufferCount++;
bufHdr = LocalBufferAlloc(reln, blockNum, &found); bufHdr = LocalBufferAlloc(smgr, blockNum, &found);
if (found) if (found)
LocalBufferHitCount++; LocalBufferHitCount++;
} }
...@@ -188,7 +227,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ...@@ -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 * lookup the buffer. IO_IN_PROGRESS is set if the requested block is
* not currently in memory. * not currently in memory.
*/ */
bufHdr = BufferAlloc(reln, blockNum, strategy, &found); bufHdr = BufferAlloc(smgr, blockNum, strategy, &found);
if (found) if (found)
BufferHitCount++; BufferHitCount++;
} }
...@@ -201,7 +240,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ...@@ -201,7 +240,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
if (!isExtend) if (!isExtend)
{ {
/* Just need to update stats before we exit */ /* Just need to update stats before we exit */
pgstat_count_buffer_hit(reln); *hit = true;
if (VacuumCostActive) if (VacuumCostActive)
VacuumCostBalance += VacuumCostPageHit; VacuumCostBalance += VacuumCostPageHit;
...@@ -225,8 +264,8 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ...@@ -225,8 +264,8 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr); bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
if (!PageIsNew((PageHeader) bufBlock)) if (!PageIsNew((PageHeader) bufBlock))
ereport(ERROR, ereport(ERROR,
(errmsg("unexpected data beyond EOF in block %u of relation \"%s\"", (errmsg("unexpected data beyond EOF in block %u of relation %u/%u/%u",
blockNum, RelationGetRelationName(reln)), 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."))); 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, ...@@ -278,8 +317,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
{ {
/* new buffers are zero-filled */ /* new buffers are zero-filled */
MemSet((char *) bufBlock, 0, BLCKSZ); MemSet((char *) bufBlock, 0, BLCKSZ);
smgrextend(reln->rd_smgr, blockNum, (char *) bufBlock, smgrextend(smgr, blockNum, (char *) bufBlock, isLocalBuf);
reln->rd_istemp);
} }
else else
{ {
...@@ -290,7 +328,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ...@@ -290,7 +328,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
if (zeroPage) if (zeroPage)
MemSet((char *) bufBlock, 0, BLCKSZ); MemSet((char *) bufBlock, 0, BLCKSZ);
else else
smgrread(reln->rd_smgr, blockNum, (char *) bufBlock); smgrread(smgr, blockNum, (char *) bufBlock);
/* check for garbage data */ /* check for garbage data */
if (!PageHeaderIsValid((PageHeader) bufBlock)) if (!PageHeaderIsValid((PageHeader) bufBlock))
{ {
...@@ -298,15 +336,20 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage, ...@@ -298,15 +336,20 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
{ {
ereport(WARNING, ereport(WARNING,
(errcode(ERRCODE_DATA_CORRUPTED), (errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page header in block %u of relation \"%s\"; zeroing out page", errmsg("invalid page header in block %u of relation %u/%u/%u; zeroing out page",
blockNum, RelationGetRelationName(reln)))); blockNum,
smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode,
smgr->smgr_rnode.relNode)));
MemSet((char *) bufBlock, 0, BLCKSZ); MemSet((char *) bufBlock, 0, BLCKSZ);
} }
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED), (errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page header in block %u of relation \"%s\"", errmsg("invalid page header in block %u of relation %u/%u/%u",
blockNum, RelationGetRelationName(reln)))); 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, ...@@ -347,7 +390,7 @@ ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
* No locks are held either at entry or exit. * No locks are held either at entry or exit.
*/ */
static volatile BufferDesc * static volatile BufferDesc *
BufferAlloc(Relation reln, BufferAlloc(SMgrRelation smgr,
BlockNumber blockNum, BlockNumber blockNum,
BufferAccessStrategy strategy, BufferAccessStrategy strategy,
bool *foundPtr) bool *foundPtr)
...@@ -364,7 +407,7 @@ BufferAlloc(Relation reln, ...@@ -364,7 +407,7 @@ BufferAlloc(Relation reln,
bool valid; bool valid;
/* create a tag so we can lookup the buffer */ /* 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 */ /* determine its hash code and partition lock ID */
newHash = BufTableHashCode(&newTag); newHash = BufTableHashCode(&newTag);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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); ...@@ -61,7 +61,7 @@ static Block GetLocalBufferStorage(void);
* (hence, usage_count is always advanced). * (hence, usage_count is always advanced).
*/ */
BufferDesc * BufferDesc *
LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) LocalBufferAlloc(SMgrRelation smgr, BlockNumber blockNum, bool *foundPtr)
{ {
BufferTag newTag; /* identity of requested block */ BufferTag newTag; /* identity of requested block */
LocalBufferLookupEnt *hresult; LocalBufferLookupEnt *hresult;
...@@ -70,7 +70,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) ...@@ -70,7 +70,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
int trycounter; int trycounter;
bool found; bool found;
INIT_BUFFERTAG(newTag, reln, blockNum); INIT_BUFFERTAG(newTag, smgr->smgr_rnode, blockNum);
/* Initialize local buffers if first request in this session */ /* Initialize local buffers if first request in this session */
if (LocalBufHash == NULL) if (LocalBufHash == NULL)
...@@ -87,7 +87,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) ...@@ -87,7 +87,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
Assert(BUFFERTAGS_EQUAL(bufHdr->tag, newTag)); Assert(BUFFERTAGS_EQUAL(bufHdr->tag, newTag));
#ifdef LBDEBUG #ifdef LBDEBUG
fprintf(stderr, "LB ALLOC (%u,%d) %d\n", fprintf(stderr, "LB ALLOC (%u,%d) %d\n",
RelationGetRelid(reln), blockNum, -b - 1); smgr->smgr_rnode.relNode, blockNum, -b - 1);
#endif #endif
/* this part is equivalent to PinBuffer for a shared buffer */ /* this part is equivalent to PinBuffer for a shared buffer */
if (LocalRefCount[b] == 0) if (LocalRefCount[b] == 0)
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -330,6 +330,13 @@ smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo)
xl_smgr_create xlrec; xl_smgr_create xlrec;
PendingRelDelete *pending; 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 * We may be using the target table space for the first time in this
* database, so create a per-database subdirectory if needed. * database, so create a per-database subdirectory if needed.
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -704,12 +704,6 @@ BuildFlatFiles(bool database_only)
rel_authid, rel_authid,
rel_authmem; 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 */ /* Need a resowner to keep the heapam and buffer code happy */
owner = ResourceOwnerCreate(NULL, "BuildFlatFiles"); owner = ResourceOwnerCreate(NULL, "BuildFlatFiles");
CurrentResourceOwner = owner; CurrentResourceOwner = owner;
...@@ -719,9 +713,15 @@ BuildFlatFiles(bool database_only) ...@@ -719,9 +713,15 @@ BuildFlatFiles(bool database_only)
rnode.dbNode = 0; rnode.dbNode = 0;
rnode.relNode = DatabaseRelationId; 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); write_database_file(rel_db, true);
FreeFakeRelcacheEntry(rel_db);
if (!database_only) if (!database_only)
{ {
...@@ -729,21 +729,21 @@ BuildFlatFiles(bool database_only) ...@@ -729,21 +729,21 @@ BuildFlatFiles(bool database_only)
rnode.spcNode = GLOBALTABLESPACE_OID; rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0; rnode.dbNode = 0;
rnode.relNode = AuthIdRelationId; rnode.relNode = AuthIdRelationId;
rel_authid = XLogOpenRelation(rnode); rel_authid = CreateFakeRelcacheEntry(rnode);
/* hard-wired path to pg_auth_members */ /* hard-wired path to pg_auth_members */
rnode.spcNode = GLOBALTABLESPACE_OID; rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0; rnode.dbNode = 0;
rnode.relNode = AuthMemRelationId; rnode.relNode = AuthMemRelationId;
rel_authmem = XLogOpenRelation(rnode); rel_authmem = CreateFakeRelcacheEntry(rnode);
write_auth_file(rel_authid, rel_authmem); write_auth_file(rel_authid, rel_authmem);
FreeFakeRelcacheEntry(rel_authid);
FreeFakeRelcacheEntry(rel_authmem);
} }
CurrentResourceOwner = NULL; CurrentResourceOwner = NULL;
ResourceOwnerDelete(owner); ResourceOwnerDelete(owner);
XLogCloseRelationCache();
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -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 bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
extern void gistcheckpage(Relation rel, Buffer buf); extern void gistcheckpage(Relation rel, Buffer buf);
extern Buffer gistNewBuffer(Relation r); extern Buffer gistNewBuffer(Relation r);
extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup, extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
int len, OffsetNumber off); OffsetNumber off);
extern IndexTuple *gistextractpage(Page page, int *len /* out */ ); extern IndexTuple *gistextractpage(Page page, int *len /* out */ );
extern IndexTuple *gistjoinvector( extern IndexTuple *gistjoinvector(
IndexTuple *itvec, int *len, IndexTuple *itvec, int *len,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, ...@@ -124,7 +124,7 @@ extern void heap_page_prune_opt(Relation relation, Buffer buffer,
extern int heap_page_prune(Relation relation, Buffer buffer, extern int heap_page_prune(Relation relation, Buffer buffer,
TransactionId OldestXmin, TransactionId OldestXmin,
bool redirect_move, bool report_stats); 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 *redirected, int nredirected,
OffsetNumber *nowdead, int ndead, OffsetNumber *nowdead, int ndead,
OffsetNumber *nowunused, int nunused, OffsetNumber *nowunused, int nunused,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #ifndef XLOG_UTILS_H
#define XLOG_UTILS_H #define XLOG_UTILS_H
...@@ -15,15 +15,15 @@ ...@@ -15,15 +15,15 @@
#include "utils/rel.h" #include "utils/rel.h"
extern void XLogInitRelationCache(void);
extern void XLogCheckInvalidPages(void); extern void XLogCheckInvalidPages(void);
extern void XLogCloseRelationCache(void);
extern Relation XLogOpenRelation(RelFileNode rnode);
extern void XLogDropRelation(RelFileNode rnode); extern void XLogDropRelation(RelFileNode rnode);
extern void XLogDropDatabase(Oid dbid); extern void XLogDropDatabase(Oid dbid);
extern void XLogTruncateRelation(RelFileNode rnode, BlockNumber nblocks); 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 #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -18,6 +18,7 @@
#include "storage/buf.h" #include "storage/buf.h"
#include "storage/lwlock.h" #include "storage/lwlock.h"
#include "storage/shmem.h" #include "storage/shmem.h"
#include "storage/smgr.h"
#include "storage/spin.h" #include "storage/spin.h"
#include "utils/rel.h" #include "utils/rel.h"
...@@ -75,9 +76,9 @@ typedef struct buftag ...@@ -75,9 +76,9 @@ typedef struct buftag
(a).blockNum = InvalidBlockNumber \ (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) \ (a).blockNum = (xx_blockNum) \
) )
...@@ -201,7 +202,7 @@ extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id); ...@@ -201,7 +202,7 @@ extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode); extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode);
/* localbuf.c */ /* localbuf.c */
extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum, extern BufferDesc *LocalBufferAlloc(SMgrRelation reln, BlockNumber blockNum,
bool *foundPtr); bool *foundPtr);
extern void MarkLocalBufferDirty(Buffer buffer); extern void MarkLocalBufferDirty(Buffer buffer);
extern void DropRelFileNodeLocalBuffers(RelFileNode rnode, extern void DropRelFileNodeLocalBuffers(RelFileNode rnode,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -145,6 +145,8 @@ extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
extern Buffer ReadBufferWithStrategy(Relation reln, BlockNumber blockNum, extern Buffer ReadBufferWithStrategy(Relation reln, BlockNumber blockNum,
BufferAccessStrategy strategy); BufferAccessStrategy strategy);
extern Buffer ReadOrZeroBuffer(Relation reln, BlockNumber blockNum); 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 ReleaseBuffer(Buffer buffer);
extern void UnlockReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer);
extern void MarkBufferDirty(Buffer buffer); extern void MarkBufferDirty(Buffer buffer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment