Refactor XLogOpenRelation() and XLogReadBuffer() in preparation for relation
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 12 Jun 2008 09:12:31 +0000 (09:12 +0000)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 12 Jun 2008 09:12:31 +0000 (09:12 +0000)
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.

20 files changed:
src/backend/access/gin/ginxlog.c
src/backend/access/gist/gist.c
src/backend/access/gist/gistutil.c
src/backend/access/gist/gistvacuum.c
src/backend/access/gist/gistxlog.c
src/backend/access/heap/heapam.c
src/backend/access/heap/pruneheap.c
src/backend/access/nbtree/nbtxlog.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogutils.c
src/backend/commands/sequence.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/backend/storage/smgr/smgr.c
src/backend/utils/init/flatfiles.c
src/include/access/gist_private.h
src/include/access/heapam.h
src/include/access/xlogutils.h
src/include/storage/buf_internals.h
src/include/storage/bufmgr.h

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