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

Reply via email to