diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-10-16 18:57:26 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-10-16 18:57:26 +0000 |
commit | fdd13f156814f81732c188788ab1b7b14c59f4da (patch) | |
tree | 2ca797d2b320de27c01ec61f5480558a05c27f4d /src/backend/storage/buffer/bufmgr.c | |
parent | 1c2de4774620469375e6393fbdbcdaffb0c2d0b5 (diff) | |
download | postgresql-fdd13f156814f81732c188788ab1b7b14c59f4da.tar.gz postgresql-fdd13f156814f81732c188788ab1b7b14c59f4da.zip |
Give the ResourceOwner mechanism full responsibility for releasing buffer
pins at end of transaction, and reduce AtEOXact_Buffers to an Assert
cross-check that this was done correctly. When not USE_ASSERT_CHECKING,
AtEOXact_Buffers is a complete no-op. This gets rid of an O(NBuffers)
bottleneck during transaction commit/abort, which recent testing has shown
becomes significant above a few tens of thousands of shared buffers.
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index a8cf506688f..b9d8fc3ad53 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.179 2004/10/16 18:05:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.180 2004/10/16 18:57:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -851,35 +851,45 @@ ResetBufferUsage(void) /* * AtEOXact_Buffers - clean up at end of transaction. * - * During abort, we need to release any buffer pins we're holding - * (this cleans up in case ereport interrupted a routine that pins a - * buffer). During commit, we shouldn't need to do that, but check - * anyway to see if anyone leaked a buffer reference count. + * As of PostgreSQL 8.0, buffer pins should get released by the + * ResourceOwner mechanism. This routine is just a debugging + * cross-check that no pins remain. */ void AtEOXact_Buffers(bool isCommit) { +#ifdef USE_ASSERT_CHECKING int i; for (i = 0; i < NBuffers; i++) { + Assert(PrivateRefCount[i] == 0); + } + + AtEOXact_LocalBuffers(isCommit); +#endif +} + +/* + * Ensure we have released all shared-buffer locks and pins during backend exit + */ +void +AtProcExit_Buffers(void) +{ + int i; + + AbortBufferIO(); + UnlockBuffers(); + + for (i = 0; i < NBuffers; i++) + { if (PrivateRefCount[i] != 0) { BufferDesc *buf = &(BufferDescriptors[i]); - if (isCommit) - elog(WARNING, - "buffer refcount leak: [%03d] " - "(rel=%u/%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)", - i, - buf->tag.rnode.spcNode, buf->tag.rnode.dbNode, - buf->tag.rnode.relNode, - buf->tag.blockNum, buf->flags, - buf->refcount, PrivateRefCount[i]); - /* - * We don't worry about updating the ResourceOwner structures; - * resowner.c will clear them for itself. + * We don't worry about updating ResourceOwner; if we even got + * here, it suggests that ResourceOwners are messed up. */ PrivateRefCount[i] = 1; /* make sure we release shared pin */ LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); @@ -888,8 +898,37 @@ AtEOXact_Buffers(bool isCommit) Assert(PrivateRefCount[i] == 0); } } +} - AtEOXact_LocalBuffers(isCommit); +/* + * Helper routine to issue warnings when a buffer is unexpectedly pinned + */ +void +PrintBufferLeakWarning(Buffer buffer) +{ + BufferDesc *buf; + int32 loccount; + + Assert(BufferIsValid(buffer)); + if (BufferIsLocal(buffer)) + { + buf = &LocalBufferDescriptors[-buffer - 1]; + loccount = LocalRefCount[-buffer - 1]; + } + else + { + buf = &BufferDescriptors[buffer - 1]; + loccount = PrivateRefCount[buffer - 1]; + } + + elog(WARNING, + "buffer refcount leak: [%03d] " + "(rel=%u/%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)", + buffer, + buf->tag.rnode.spcNode, buf->tag.rnode.dbNode, + buf->tag.rnode.relNode, + buf->tag.blockNum, buf->flags, + buf->refcount, loccount); } /* |