diff options
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 41ee78e547c..ae4a29d6070 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.87 2000/10/18 05:50:15 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.88 2000/10/20 11:01:07 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -2481,3 +2481,56 @@ AbortBufferIO(void) SpinRelease(BufMgrLock); } } + +/* + * Cleanup buffer or mark it for cleanup. Buffer may be cleaned + * up if it's pinned only once. + * + * NOTE: buffer must be excl locked. + */ +void +MarkBufferForCleanup(Buffer buffer, void (*CleanupFunc)(Buffer)) +{ + BufferDesc *bufHdr = &BufferDescriptors[buffer - 1]; + + Assert(PrivateRefCount[buffer - 1] > 0); + + if (PrivateRefCount[buffer - 1] > 1) + { + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + PrivateRefCount[buffer - 1]--; + SpinAcquire(BufMgrLock); + Assert(bufHdr->refcount > 0); + bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); + bufHdr->CleanupFunc = CleanupFunc; + SpinRelease(BufMgrLock); + return; + } + + SpinAcquire(BufMgrLock); + Assert(bufHdr->refcount > 0); + if (bufHdr->refcount == 1) + { + SpinRelease(BufMgrLock); + CleanupFunc(buffer); + CleanupFunc = NULL; + } + else + SpinRelease(BufMgrLock); + + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + PrivateRefCount[buffer - 1]--; + + SpinAcquire(BufMgrLock); + Assert(bufHdr->refcount > 0); + bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); + bufHdr->CleanupFunc = CleanupFunc; + bufHdr->refcount--; + if (bufHdr->refcount == 0) + { + AddBufferToFreelist(bufHdr); + bufHdr->flags |= BM_FREE; + } + SpinRelease(BufMgrLock); + return; +} |