mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
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.
This commit is contained in:
parent
c4f2a0458d
commit
a213f1ee6c
@ -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
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
|
|
||||||
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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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)
|
|||||||
|
|
||||||
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
|
|||||||
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 @@
|
|||||||
* 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];
|
|||||||
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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* enough free space */
|
/* enough free space */
|
||||||
gistfillbuffer(gv->index, tempPage, addon, curlenaddon, InvalidOffsetNumber);
|
gistfillbuffer(tempPage, addon, curlenaddon, InvalidOffsetNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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
|
|||||||
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)
|
|||||||
* 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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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:;
|
|||||||
|
|
||||||
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:;
|
|||||||
}
|
}
|
||||||
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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
* 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)
|
|||||||
* 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 @@
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
/* 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
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
/* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|||||||
|
|
||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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 @@
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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 @@
|
|||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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;
|
RelationData reldata; /* Note: this must be first */
|
||||||
struct XLogRelDesc *lessRecently;
|
FormData_pg_class pgc;
|
||||||
struct XLogRelDesc *moreRecently;
|
} FakeRelCacheEntryData;
|
||||||
} XLogRelDesc;
|
|
||||||
|
|
||||||
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;
|
FakeRelCacheEntry fakeentry;
|
||||||
XLogRelDesc *rdesc;
|
Relation rel;
|
||||||
} XLogRelCacheEntry;
|
|
||||||
|
|
||||||
static HTAB *_xlrelcache;
|
/* Allocate the Relation struct and all related space in one block. */
|
||||||
static XLogRelDesc *_xlrelarr = NULL;
|
fakeentry = palloc0(sizeof(FakeRelCacheEntryData));
|
||||||
static Form_pg_class _xlpgcarr = NULL;
|
rel = (Relation) fakeentry;
|
||||||
static int _xlast = 0;
|
|
||||||
static int _xlcnt = 0;
|
|
||||||
|
|
||||||
#define _XLOG_RELCACHESIZE 512
|
rel->rd_rel = &fakeentry->pgc;
|
||||||
|
rel->rd_node = rnode;
|
||||||
|
|
||||||
static void
|
/* We don't know the name of the relation; use relfilenode instead */
|
||||||
_xl_init_rel_cache(void)
|
sprintf(RelationGetRelationName(rel), "%u", rnode.relNode);
|
||||||
{
|
|
||||||
HASHCTL ctl;
|
|
||||||
|
|
||||||
_xlcnt = _XLOG_RELCACHESIZE;
|
/*
|
||||||
_xlast = 0;
|
* We set up the lockRelId in case anything tries to lock the dummy
|
||||||
_xlrelarr = (XLogRelDesc *) malloc(sizeof(XLogRelDesc) * _xlcnt);
|
* relation. Note that this is fairly bogus since relNode may be
|
||||||
memset(_xlrelarr, 0, sizeof(XLogRelDesc) * _xlcnt);
|
* different from the relation's OID. It shouldn't really matter
|
||||||
_xlpgcarr = (Form_pg_class) malloc(sizeof(FormData_pg_class) * _xlcnt);
|
* though, since we are presumably running by ourselves and can't have
|
||||||
memset(_xlpgcarr, 0, sizeof(FormData_pg_class) * _xlcnt);
|
* any lock conflicts ...
|
||||||
|
*/
|
||||||
|
rel->rd_lockInfo.lockRelId.dbId = rnode.dbNode;
|
||||||
|
rel->rd_lockInfo.lockRelId.relId = rnode.relNode;
|
||||||
|
|
||||||
_xlrelarr[0].moreRecently = &(_xlrelarr[0]);
|
rel->rd_targblock = InvalidBlockNumber;
|
||||||
_xlrelarr[0].lessRecently = &(_xlrelarr[0]);
|
rel->rd_smgr = NULL;
|
||||||
|
|
||||||
memset(&ctl, 0, sizeof(ctl));
|
return rel;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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;
|
|||||||
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);
|
|||||||
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);
|
|||||||
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
|
|||||||
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,
|
|||||||
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
|
static Buffer
|
||||||
ReadBuffer_common(Relation reln, BlockNumber blockNum, bool zeroPage,
|
ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
|
||||||
BufferAccessStrategy strategy)
|
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;
|
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,
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
* 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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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);
|
|||||||
* (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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
* 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);
|
|||||||
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 @@
|
|||||||
* 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,
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
#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 @@
|
|||||||
* 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 @@
|
|||||||
#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
|
|||||||
(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);
|
|||||||
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 @@
|
|||||||
* 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);
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user