This patch changes PrivateRefCount and LocalRefCount in the bufmgr from being arrays of long to arrays of int32, per earlier discussion. This should save a little memory on 64LP machines, and there's no way we need to track > 2^31 references to a single buffer.
I also fixed the rather widespread assumption that a BufferDesc's refcount is signed; it is not (and hence the correct printf formatting code is %u, not %d). I also changed ShowPinTrace to a bool, and removed some multi-line string literals (yuck!) Barring any objections, I intend to apply this patch within 24 hours. -Neil
Index: src/backend/storage/buffer/buf_init.c =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/backend/storage/buffer/buf_init.c,v retrieving revision 1.63 diff -c -r1.63 buf_init.c *** a/src/backend/storage/buffer/buf_init.c 19 Apr 2004 23:27:17 -0000 1.63 --- b/src/backend/storage/buffer/buf_init.c 21 Apr 2004 19:34:45 -0000 *************** *** 21,27 **** BufferDesc *BufferDescriptors; Block *BufferBlockPointers; ! long *PrivateRefCount; /* also used in freelist.c */ bits8 *BufferLocks; /* flag bits showing locks I have set */ /* statistics counters */ --- 21,27 ---- BufferDesc *BufferDescriptors; Block *BufferBlockPointers; ! int32 *PrivateRefCount; /* also used in freelist.c */ bits8 *BufferLocks; /* flag bits showing locks I have set */ /* statistics counters */ *************** *** 176,184 **** /* * Allocate and zero local arrays of per-buffer info. */ ! BufferBlockPointers = (Block *) calloc(NBuffers, sizeof(Block)); ! PrivateRefCount = (long *) calloc(NBuffers, sizeof(long)); ! BufferLocks = (bits8 *) calloc(NBuffers, sizeof(bits8)); /* * Convert shmem offsets into addresses as seen by this process. This --- 176,184 ---- /* * Allocate and zero local arrays of per-buffer info. */ ! BufferBlockPointers = calloc(NBuffers, sizeof(*BufferBlockPointers)); ! PrivateRefCount = calloc(NBuffers, sizeof(*PrivateRefCount)); ! BufferLocks = calloc(NBuffers, sizeof(*BufferLocks)); /* * Convert shmem offsets into addresses as seen by this process. This Index: src/backend/storage/buffer/bufmgr.c =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/backend/storage/buffer/bufmgr.c,v retrieving revision 1.161 diff -c -r1.161 bufmgr.c *** a/src/backend/storage/buffer/bufmgr.c 19 Apr 2004 23:27:17 -0000 1.161 --- b/src/backend/storage/buffer/bufmgr.c 21 Apr 2004 19:44:49 -0000 *************** *** 65,71 **** bool zero_damaged_pages = false; #ifdef NOT_USED ! int ShowPinTrace = 0; #endif int BgWriterDelay = 200; --- 65,71 ---- bool zero_damaged_pages = false; #ifdef NOT_USED ! bool ShowPinTrace = false; #endif int BgWriterDelay = 200; *************** *** 974,980 **** if (isCommit) elog(WARNING, "buffer refcount leak: [%03d] " ! "(rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, --- 974,980 ---- if (isCommit) elog(WARNING, "buffer refcount leak: [%03d] " ! "(rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, *************** *** 1311,1317 **** { /* the sole pin should be ours */ if (bufHdr->refcount != 1 || PrivateRefCount[i - 1] == 0) ! elog(FATAL, "block %u of %u/%u is still referenced (private %ld, global %d)", bufHdr->tag.blockNum, bufHdr->tag.rnode.tblNode, bufHdr->tag.rnode.relNode, --- 1311,1317 ---- { /* the sole pin should be ours */ if (bufHdr->refcount != 1 || PrivateRefCount[i - 1] == 0) ! elog(FATAL, "block %u of %u/%u is still referenced (private %d, global %u)", bufHdr->tag.blockNum, bufHdr->tag.rnode.tblNode, bufHdr->tag.rnode.relNode, *************** *** 1416,1423 **** LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); for (i = 0; i < NBuffers; ++i, ++buf) { ! elog(LOG, "[%02d] (freeNext=%d, freePrev=%d, rel=%u/%u, \ ! blockNum=%u, flags=0x%x, refcount=%d %ld)", i, buf->freeNext, buf->freePrev, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, --- 1416,1424 ---- LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); for (i = 0; i < NBuffers; ++i, ++buf) { ! elog(LOG, ! "[%02d] (freeNext=%d, freePrev=%d, rel=%u/%u, " ! "blockNum=%u, flags=0x%x, refcount=%u %d)", i, buf->freeNext, buf->freePrev, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, *************** *** 1430,1436 **** /* interactive backend */ for (i = 0; i < NBuffers; ++i, ++buf) { ! printf("[%-2d] (%u/%u, %u) flags=0x%x, refcnt=%d %ld)\n", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, buf->refcount, PrivateRefCount[i]); --- 1431,1437 ---- /* interactive backend */ for (i = 0; i < NBuffers; ++i, ++buf) { ! printf("[%-2d] (%u/%u, %u) flags=0x%x, refcount=%u %d)\n", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, buf->refcount, PrivateRefCount[i]); *************** *** 1450,1457 **** for (i = 0; i < NBuffers; ++i, ++buf) { if (PrivateRefCount[i] > 0) ! elog(WARNING, "[%02d] (freeNext=%d, freePrev=%d, rel=%u/%u, \ ! blockNum=%u, flags=0x%x, refcount=%d %ld)", i, buf->freeNext, buf->freePrev, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, --- 1451,1459 ---- for (i = 0; i < NBuffers; ++i, ++buf) { if (PrivateRefCount[i] > 0) ! elog(WARNING, ! "[%02d] (freeNext=%d, freePrev=%d, rel=%u/%u, " ! "blockNum=%u, flags=0x%x, refcount=%u %d)", i, buf->freeNext, buf->freePrev, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, *************** *** 1540,1546 **** 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]); return (-2); --- 1542,1548 ---- if (LocalRefCount[i] > 0) { error_context_stack = errcontext.previous; ! elog(WARNING, "FlushRelationBuffers(\"%s\" (local), %u): block %u is referenced (%d)", RelationGetRelationName(rel), firstDelBlock, bufHdr->tag.blockNum, LocalRefCount[i]); return (-2); *************** *** 1622,1628 **** { 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, PrivateRefCount[i], bufHdr->refcount); --- 1624,1630 ---- { LWLockRelease(BufMgrLock); error_context_stack = errcontext.previous; ! elog(WARNING, "FlushRelationBuffers(\"%s\", %u): block %u is referenced (private %d, global %u)", RelationGetRelationName(rel), firstDelBlock, bufHdr->tag.blockNum, PrivateRefCount[i], bufHdr->refcount); *************** *** 1684,1691 **** { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, "PIN(Incr) %d rel = %u/%u, blockNum = %u, \ ! refcount = %ld, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, --- 1686,1694 ---- { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, ! "PIN(Incr) %d rel = %u/%u, blockNum = %u, " ! "refcount = %d, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, *************** *** 1703,1710 **** { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, "UNPIN(Rel) %d rel = %u/%u, blockNum = %u, \ ! refcount = %ld, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, --- 1706,1714 ---- { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, ! "UNPIN(Rel) %d rel = %u/%u, blockNum = %u, " ! "refcount = %d, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, *************** *** 1731,1738 **** { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, "UNPIN(Rel&Rd) %d rel = %u/%u, blockNum = %u, \ ! refcount = %ld, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, --- 1735,1743 ---- { BufferDesc *buf = &BufferDescriptors[buffer - 1]; ! fprintf(stderr, ! "UNPIN(Rel&Rd) %d rel = %u/%u, blockNum = %u, " ! "refcount = %d, file: %s, line: %d\n", buffer, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, *************** *** 1742,1749 **** { BufferDesc *buf = &BufferDescriptors[b - 1]; ! fprintf(stderr, "PIN(Rel&Rd) %d rel = %u/%u, blockNum = %u, \ ! refcount = %ld, file: %s, line: %d\n", b, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, --- 1747,1755 ---- { BufferDesc *buf = &BufferDescriptors[b - 1]; ! fprintf(stderr, ! "PIN(Rel&Rd) %d rel = %u/%u, blockNum = %u, " ! "refcount = %d, file: %s, line: %d\n", b, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, *************** *** 1938,1944 **** { /* There should be exactly one pin */ if (LocalRefCount[-buffer - 1] != 1) ! elog(ERROR, "incorrect local pin count: %ld", LocalRefCount[-buffer - 1]); /* Nobody else to wait for */ return; --- 1944,1950 ---- { /* There should be exactly one pin */ if (LocalRefCount[-buffer - 1] != 1) ! elog(ERROR, "incorrect local pin count: %d", LocalRefCount[-buffer - 1]); /* Nobody else to wait for */ return; *************** *** 1946,1952 **** /* There should be exactly one local pin */ if (PrivateRefCount[buffer - 1] != 1) ! elog(ERROR, "incorrect local pin count: %ld", PrivateRefCount[buffer - 1]); bufHdr = &BufferDescriptors[buffer - 1]; --- 1952,1958 ---- /* There should be exactly one local pin */ if (PrivateRefCount[buffer - 1] != 1) ! elog(ERROR, "incorrect local pin count: %d", PrivateRefCount[buffer - 1]); bufHdr = &BufferDescriptors[buffer - 1]; Index: src/backend/storage/buffer/localbuf.c =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/backend/storage/buffer/localbuf.c,v retrieving revision 1.52 diff -c -r1.52 localbuf.c *** a/src/backend/storage/buffer/localbuf.c 10 Feb 2004 01:55:25 -0000 1.52 --- b/src/backend/storage/buffer/localbuf.c 21 Apr 2004 19:39:40 -0000 *************** *** 28,34 **** BufferDesc *LocalBufferDescriptors = NULL; Block *LocalBufferBlockPointers = NULL; ! long *LocalRefCount = NULL; static int nextFreeLocalBuf = 0; --- 28,34 ---- BufferDesc *LocalBufferDescriptors = NULL; Block *LocalBufferBlockPointers = NULL; ! int32 *LocalRefCount = NULL; static int nextFreeLocalBuf = 0; *************** *** 183,192 **** /* * these aren't going away. I'm not gonna use palloc. */ ! LocalBufferDescriptors = ! (BufferDesc *) calloc(NLocBuffer, sizeof(BufferDesc)); ! LocalBufferBlockPointers = (Block *) calloc(NLocBuffer, sizeof(Block)); ! LocalRefCount = (long *) calloc(NLocBuffer, sizeof(long)); nextFreeLocalBuf = 0; for (i = 0; i < NLocBuffer; i++) --- 183,193 ---- /* * these aren't going away. I'm not gonna use palloc. */ ! LocalBufferDescriptors = calloc(NLocBuffer, ! sizeof(*LocalBufferDescriptors)); ! LocalBufferBlockPointers = calloc(NLocBuffer, ! sizeof(*LocalBufferBlockPointers)); ! LocalRefCount = calloc(NLocBuffer, sizeof(*LocalRefCount)); nextFreeLocalBuf = 0; for (i = 0; i < NLocBuffer; i++) *************** *** 221,227 **** if (isCommit) elog(WARNING, ! "local buffer leak: [%03d] (rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, --- 222,228 ---- if (isCommit) elog(WARNING, ! "local buffer leak: [%03d] (rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)", i, buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags, Index: src/include/storage/bufmgr.h =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/include/storage/bufmgr.h,v retrieving revision 1.75 diff -c -r1.75 bufmgr.h *** a/src/include/storage/bufmgr.h 4 Feb 2004 01:24:53 -0000 1.75 --- b/src/include/storage/bufmgr.h 21 Apr 2004 19:32:33 -0000 *************** *** 35,46 **** /* in buf_init.c */ extern DLLIMPORT Block *BufferBlockPointers; ! extern long *PrivateRefCount; /* in localbuf.c */ extern DLLIMPORT int NLocBuffer; extern DLLIMPORT Block *LocalBufferBlockPointers; ! extern long *LocalRefCount; /* special pageno for bget */ #define P_NEW InvalidBlockNumber /* grow the file to get a new page */ --- 35,46 ---- /* in buf_init.c */ extern DLLIMPORT Block *BufferBlockPointers; ! extern int32 *PrivateRefCount; /* in localbuf.c */ extern DLLIMPORT int NLocBuffer; extern DLLIMPORT Block *LocalBufferBlockPointers; ! extern int32 *LocalRefCount; /* special pageno for bget */ #define P_NEW InvalidBlockNumber /* grow the file to get a new page */
---------------------------(end of broadcast)--------------------------- TIP 7: don't forget to increase your free space map settings