OSDN Git Service

Make use of new error context stack mechanism to allow random errors
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 May 2003 19:04:30 +0000 (19:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 May 2003 19:04:30 +0000 (19:04 +0000)
detected during buffer dump to be labeled with the buffer location.
For example, if a page LSN is clobbered, we now produce something like
ERROR:  XLogFlush: request 2C000000/8468EC8 is not satisfied --- flushed only
to 0/8468EF0
CONTEXT:  writing block 0 of relation 428946/566240
whereas before there was no convenient way to find out which page had
been trashed.

src/backend/storage/buffer/bufmgr.c

index 119cfe9..89087f0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.135 2003/03/28 20:17:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.136 2003/05/10 19:04:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,6 +68,7 @@ static void WaitIO(BufferDesc *buf);
 static void StartBufferIO(BufferDesc *buf, bool forInput);
 static void TerminateBufferIO(BufferDesc *buf);
 static void ContinueBufferIO(BufferDesc *buf, bool forInput);
+static void buffer_write_error_callback(void *arg);
 
 /*
  * Macro : BUFFER_IS_BROKEN
@@ -699,14 +700,24 @@ BufferSync(void)
 {
        int                     i;
        BufferDesc *bufHdr;
-       Buffer          buffer;
-       int                     status;
-       RelFileNode rnode;
-       XLogRecPtr      recptr;
-       Relation        reln = NULL;
+       ErrorContextCallback errcontext;
+
+       /* Setup error traceback support for ereport() */
+       errcontext.callback = buffer_write_error_callback;
+       errcontext.arg = NULL;
+       errcontext.previous = error_context_stack;
+       error_context_stack = &errcontext;
 
        for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
        {
+               Buffer          buffer;
+               int                     status;
+               RelFileNode rnode;
+               XLogRecPtr      recptr;
+               Relation        reln;
+
+               errcontext.arg = bufHdr;
+
                LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 
                if (!(bufHdr->flags & BM_VALID))
@@ -834,6 +845,8 @@ BufferSync(void)
                        RelationDecrementReferenceCount(reln);
        }
 
+       /* Pop the error context stack */
+       error_context_stack = errcontext.previous;
 }
 
 /*
@@ -1011,12 +1024,19 @@ BufferReplace(BufferDesc *bufHdr)
        Relation        reln;
        XLogRecPtr      recptr;
        int                     status;
+       ErrorContextCallback errcontext;
 
        /* To check if block content changed while flushing. - vadim 01/17/97 */
        bufHdr->flags &= ~BM_JUST_DIRTIED;
 
        LWLockRelease(BufMgrLock);
 
+       /* Setup error traceback support for ereport() */
+       errcontext.callback = buffer_write_error_callback;
+       errcontext.arg = bufHdr;
+       errcontext.previous = error_context_stack;
+       error_context_stack = &errcontext;
+
        /*
         * No need to lock buffer context - no one should be able to end
         * ReadBuffer
@@ -1043,6 +1063,9 @@ BufferReplace(BufferDesc *bufHdr)
        if (reln != (Relation) NULL)
                RelationDecrementReferenceCount(reln);
 
+       /* Pop the error context stack */
+       error_context_stack = errcontext.previous;
+
        LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 
        if (status == SM_FAIL)
@@ -1380,12 +1403,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
        BufferDesc *bufHdr;
        XLogRecPtr      recptr;
        int                     status;
+       ErrorContextCallback errcontext;
+
+       /* Setup error traceback support for ereport() */
+       errcontext.callback = buffer_write_error_callback;
+       errcontext.arg = NULL;
+       errcontext.previous = error_context_stack;
+       error_context_stack = &errcontext;
 
        if (rel->rd_istemp)
        {
                for (i = 0; i < NLocBuffer; i++)
                {
                        bufHdr = &LocalBufferDescriptors[i];
+                       errcontext.arg = bufHdr;
                        if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
                        {
                                if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1395,6 +1426,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                                                                           (char *) MAKE_PTR(bufHdr->data));
                                        if (status == SM_FAIL)
                                        {
+                                               error_context_stack = errcontext.previous;
                                                elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
                                                         RelationGetRelationName(rel), firstDelBlock,
                                                         bufHdr->tag.blockNum);
@@ -1405,6 +1437,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                                }
                                if (LocalRefCount[i] > 0)
                                {
+                                       error_context_stack = errcontext.previous;
                                        elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
                                                 RelationGetRelationName(rel), firstDelBlock,
                                                 bufHdr->tag.blockNum, LocalRefCount[i]);
@@ -1414,6 +1447,10 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                                        bufHdr->tag.rnode.relNode = InvalidOid;
                        }
                }
+
+               /* Pop the error context stack */
+               error_context_stack = errcontext.previous;
+
                return 0;
        }
 
@@ -1422,6 +1459,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
        for (i = 0; i < NBuffers; i++)
        {
                bufHdr = &BufferDescriptors[i];
+               errcontext.arg = bufHdr;
                if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
                {
                        if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1483,6 +1521,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                        if (!(bufHdr->flags & BM_FREE))
                        {
                                LWLockRelease(BufMgrLock);
+                               error_context_stack = errcontext.previous;
                                elog(WARNING, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
                                         RelationGetRelationName(rel), firstDelBlock,
                                         bufHdr->tag.blockNum,
@@ -1493,7 +1532,12 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                                BufTableDelete(bufHdr);
                }
        }
+
        LWLockRelease(BufMgrLock);
+
+       /* Pop the error context stack */
+       error_context_stack = errcontext.previous;
+
        return 0;
 }
 
@@ -2083,3 +2127,17 @@ BufferGetFileNode(Buffer buffer)
 
        return (bufHdr->tag.rnode);
 }
+
+/*
+ * Error context callback for errors occurring during buffer writes.
+ */
+static void
+buffer_write_error_callback(void *arg)
+{
+       BufferDesc *bufHdr = (BufferDesc *) arg;
+
+       if (bufHdr != NULL)
+               errcontext("writing block %u of relation %u/%u",
+                                  bufHdr->tag.blockNum,
+                                  bufHdr->tag.rnode.tblNode, bufHdr->tag.rnode.relNode);
+}