Return-Path: owner-postman
Received: from localhost.Berkeley.EDU (localhost.Berkeley.EDU [127.0.0.1]) by nobozo.CS.Berkeley.EDU (8.6.9/8.6.3) with SMTP id AAA23796 for postgres-redist; Thu, 25 Aug 1994 00:13:25 -0700
Resent-From: POSTGRES mailing list <postman@postgres.Berkeley.EDU>
Resent-Message-Id: <199408250713.AAA23796@nobozo.CS.Berkeley.EDU>
Sender: owner-postman@postgres.Berkeley.EDU
X-Return-Path: owner-postman
Received: from faerie.CS.Berkeley.EDU (faerie.CS.Berkeley.EDU [128.32.37.53]) by nobozo.CS.Berkeley.EDU (8.6.9/8.6.3) with ESMTP id AAA23786 for <postgres@postgres.Berkeley.EDU>; Thu, 25 Aug 1994 00:13:24 -0700
Received: from localhost.Berkeley.EDU (localhost.Berkeley.EDU [127.0.0.1]) by faerie.CS.Berkeley.EDU (8.6.9/8.1B) with SMTP id AAA24838; Thu, 25 Aug 1994 00:13:19 -0700
Message-Id: <199408250713.AAA24838@faerie.CS.Berkeley.EDU>
X-Authentication-Warning: faerie.CS.Berkeley.EDU: Host localhost.Berkeley.EDU didn't use HELO protocol
From: aoki@cs.berkeley.edu (Paul M. Aoki)
To: postgres@postgres.Berkeley.EDU
Reply-To: aoki@cs.berkeley.edu (Paul M. Aoki)
Subject: some random hacks...
Date: Thu, 25 Aug 94 00:13:13 -0700
X-Sender: aoki@postgres.Berkeley.EDU
Resent-To: postgres-redist@postgres.Berkeley.EDU
X-Mts: smtp
Resent-Date: Thu, 25 Aug 94 00:13:25 -0700
Resent-XMts: smtp

here are some context diffs.  they haven't been tested with any great
rigor, you're on your own with these -- however, all but the one that
is described last should be (at worst) innocuous on any system.
still, save the old versions of your source in case you have to back
out a change.

(1) newbki.sh: i managed to break newbki, which is not so bad
considering that the documentation for it was removed in 4.2, but
here's a fix anyway.  apply it.

(2) postgres.faq: the FAQ is updated a bit.

(3) postmaster.c: i threw in the environment variable fix that someone
mentioned for the occasional "database xxx does not exist, bailing
out..." that plagues some ports.  this is probably a good one to apply
-- it does seem to help under DEC OSF/1 2.0 and OSF/1 2.1, i don't
know about other ports.

(4) *all* of the other changes: spinlocks and some routines that use
shared memory were kludged (to put it kindly) to work on
multiprocessor sables (DEC 2100/A500MPs running the field-test DEC
OSF/1 T3.0-2 (Rev. 307.2) -- these are hellishly cool boxes, every kid
should have one!).  if you *don't* have a multiprocessor sable, you
may not want to apply these changes, since it is likely to slow things
down on the platforms that don't have spinlocks (just ultrix, at this
point, but if it ain't broke don't fix it, right?).
--
  Paul M. Aoki          |  University of California at Berkeley
  aoki@CS.Berkeley.EDU  |  Dept. of EECS, Computer Science Division (#1776)
                        |  Berkeley, CA 94720-1776


*** postgres-v4r2/./src/bin/newbki/newbki.sh	Sun Dec 12 15:13:16 1993
--- postgres/./src/bin/newbki/newbki.sh	Fri Jul 15 01:24:25 1994
***************
*** 52,57 ****
  for i in *.source
  do
  	dest=`echo $i | sed 's/\.source$//'`
! 	sed -e "s/postgres PGUID/$name $pguid/" < $i > $dest
  done
  echo "Done.  You must now run initdb."
--- 52,58 ----
  for i in *.source
  do
  	dest=`echo $i | sed 's/\.source$//'`
! 	sed -e "s/postgres PGUID/$name $pguid/" \
! 	    -e "s/PGUID/$pguid/" < $i > $dest
  done
  echo "Done.  You must now run initdb."
*** postgres-v4r2/./src/doc/postgres.faq	Thu Mar 31 00:58:54 1994
--- postgres/./src/doc/postgres.faq	Wed Jul 13 11:32:14 1994
***************
*** 94,109 ****
  Q.  What about SQL support?
  
  A.  POSTGRES does not support SQL.  A commercial version of POSTGRES
!     produced by Montage Software, Inc. (see below) does support SQL.
  
  Q.  What does POSTGRES run on?
  
  A.  POSTGRES 4.2 is known to run on Sun-4 (SPARC) computers running SunOS
!     4.1.2 or higher, DECstation 3100 and 5000 (MIPS) computers running
!     Ultrix 4.2 or higher, H-P 9000 Model 700 and 800 (PA-RISC)
      computers running HP-UX 9.00 or higher, DECstation 3000 (Alpha
!     AXP) running OSF/1 1.3, and IBM RS/6000 (POWER) running AIX 3.2.3
!     or higher.
  
      The experience of outside developers indicates that POSTGRES is
      relatively easy to port to any system that supports:
--- 94,110 ----
  Q.  What about SQL support?
  
  A.  POSTGRES does not support SQL.  A commercial version of POSTGRES
!     produced by Illustra Information Technologies, Inc. (see below)
!     does support SQL.
  
  Q.  What does POSTGRES run on?
  
  A.  POSTGRES 4.2 is known to run on Sun-4 (SPARC) computers running SunOS
!     4.1.3 and Solaris 2.3, DECstation 3100 and 5000 (MIPS) computers
!     running Ultrix 4.2 or higher, H-P 9000 Model 700 and 800 (PA-RISC)
      computers running HP-UX 9.00 or higher, DECstation 3000 (Alpha
!     AXP) running OSF/1 1.3 and 2.0, and IBM RS/6000 (POWER) running
!     AIX 3.2.5 or higher.
  
      The experience of outside developers indicates that POSTGRES is
      relatively easy to port to any system that supports:
***************
*** 212,226 ****
  
  Q.  Is there a commercial version of POSTGRES?
  
! A.  Yes.  Montage Software, Inc. has performed a substantial amount of
      bullet-proofing and performance improvement and has added many new
      features (true log-based crash recovery, an type system that makes
!     sense, SQL support).  They also provide technical support.  You can
!     contact them at:
  
! 	Montage Software, Inc.
  	1111 Broadway, Suite 2000
  	Oakland, CA 94607
  	510-652-8000
  	510-652-8050 (fax)
! 	sales@montage.com
--- 213,228 ----
  
  Q.  Is there a commercial version of POSTGRES?
  
! A.  Yes.  Illustra Information Technologies (formerly Montage
!     Software, Inc.( has performed a substantial amount of
      bullet-proofing and performance improvement and has added many new
      features (true log-based crash recovery, an type system that makes
!     sense, SQL support).  They also provide technical support.  You
!     can contact them at:
  
! 	Illustra Information Technologies, Inc.
  	1111 Broadway, Suite 2000
  	Oakland, CA 94607
  	510-652-8000
  	510-652-8050 (fax)
! 	sales@illustra.com
*** postgres-v4r2/./src/backend/postmaster/postmaster.c	Wed Jun 15 20:23:06 1994
--- postgres/./src/backend/postmaster/postmaster.c	Wed Aug 24 17:58:12 1994
***************
*** 1,5 ****
  /*
!  * /usr/local/devel/postgres-v4r2/src/backend/postmaster/RCS/postmaster.c,v 1.79 1994/06/16 03:23:06 aoki Exp
   *
   *	POSTMASTER
   *
--- 1,5 ----
  /*
!  * $Header: /usr/local/devel/postgres/src/backend/postmaster/RCS/postmaster.c,v 1.80 1994/08/25 00:57:59 aoki Exp $
   *
   *	POSTMASTER
   *
***************
*** 708,720 ****
  {
      int		status = 0;	/* return status */
      BackendNode	*bn;		/* for backend cleanup */
!     int		pid;
!     char		envEntry[4][2 * ARGV_SIZE];
      
      /*
       * Set up the necessary environment variables for the backend
       * This should really be some sort of message....
       */
      sprintf(envEntry[0], "POSTPORT=%d", PostPortName);
      putenv(envEntry[0]);
      sprintf(envEntry[1], "POSTID=%d", NextBackendId);
--- 708,723 ----
  {
      int		status = 0;	/* return status */
      BackendNode	*bn;		/* for backend cleanup */
!     int		i, pid;
!     char	*envEntry[4];
      
      /*
       * Set up the necessary environment variables for the backend
       * This should really be some sort of message....
       */
+     for (i = 0; i < 4; ++i) {
+ 	envEntry[i] = calloc(2 * ARGV_SIZE, 1);
+     }
      sprintf(envEntry[0], "POSTPORT=%d", PostPortName);
      putenv(envEntry[0]);
      sprintf(envEntry[1], "POSTID=%d", NextBackendId);
*** postgres-v4r2/./src/backend/port/alpha/Makefile.inc	Wed Jun 15 20:23:06 1994
--- postgres/./src/backend/port/alpha/Makefile.inc	Mon Jul 18 18:40:55 1994
***************
*** 1,7 ****
  #
  # Alpha OSF/1 specific stuff
  #
! # /usr/local/devel/postgres-v4r2/src/backend/port/alpha/RCS/Makefile.inc,v 1.10 1994/06/16 03:23:06 aoki Exp
  #
  
  CFLAGS+= -DUSE_POSIX_TIME -DDISABLE_XOPEN_NLS -DNEED_ISINF -DHAS_LONG_LONG
--- 1,7 ----
  #
  # Alpha OSF/1 specific stuff
  #
! # $Header: /usr/local/devel/postgres/src/backend/port/alpha/RCS/Makefile.inc,v 1.11 1994/07/19 01:40:46 aoki Exp $
  #
  
  CFLAGS+= -DUSE_POSIX_TIME -DDISABLE_XOPEN_NLS -DNEED_ISINF -DHAS_LONG_LONG
***************
*** 17,20 ****
  
  HEADERS+= machine.h 
  
! SRCS+= dynloader.c port.c tas.s
--- 17,20 ----
  
  HEADERS+= machine.h 
  
! SRCS+= dynloader.c port.c
*** postgres-v4r2/./src/backend/storage/ipc.h	Fri Jun 24 17:43:46 1994
--- postgres/./src/backend/storage/ipc.h	Mon Jul 18 18:41:10 1994
***************
*** 10,16 ****
   *	be factored into the port/ directories.
   *
   *   IDENTIFICATION
!  *	/usr/local/devel/postgres-v4r2/src/backend/storage/RCS/ipc.h,v 1.42 1994/06/25 00:43:46 aoki Exp
   */
  
  #ifndef	IPCIncluded	/* Include this file only once */
--- 10,16 ----
   *	be factored into the port/ directories.
   *
   *   IDENTIFICATION
!  *	$Header: /usr/local/devel/postgres/src/backend/storage/RCS/ipc.h,v 1.43 1994/07/19 01:41:04 aoki Exp $
   */
  
  #ifndef	IPCIncluded	/* Include this file only once */
***************
*** 62,71 ****
  typedef unsigned int	slock_t;
  #else /* aix */
  #if defined(PORTNAME_alpha)
! /*
!  * The Alpha LDQ_L/STQ_C instructions operate on quadwords (long int).
!  */
! typedef long		slock_t;
  #else /* alpha */
  #if defined(PORTNAME_hpux)
  /*
--- 62,69 ----
  typedef unsigned int	slock_t;
  #else /* aix */
  #if defined(PORTNAME_alpha)
! #include <sys/mman.h>
! typedef msemaphore	slock_t;
  #else /* alpha */
  #if defined(PORTNAME_hpux)
  /*
***************
*** 91,97 ****
  extern int S_UNLOCK ARGS((slock_t *lock));
  extern int S_INIT_LOCK ARGS((slock_t *lock));
  
! #if defined(PORTNAME_hpux)
  extern int S_LOCK_FREE ARGS((slock_t *lock));
  #else /* PORTNAME_hpux */
  #define S_LOCK_FREE(lock)	((*lock) == 0)
--- 89,95 ----
  extern int S_UNLOCK ARGS((slock_t *lock));
  extern int S_INIT_LOCK ARGS((slock_t *lock));
  
! #if defined(PORTNAME_hpux) || defined(PORTNAME_alpha)
  extern int S_LOCK_FREE ARGS((slock_t *lock));
  #else /* PORTNAME_hpux */
  #define S_LOCK_FREE(lock)	((*lock) == 0)
*** postgres-v4r2/./src/backend/storage/buffer/bufmgr.c	Fri Jun 24 17:43:46 1994
--- postgres/./src/backend/storage/buffer/bufmgr.c	Mon Jul 18 18:46:00 1994
***************
*** 2,8 ****
   * bufmgr.c -- buffer manager interface routines
   *
   * Identification:
!  *	/usr/local/devel/postgres-v4r2/src/backend/storage/buffer/RCS/bufmgr.c,v 1.83 1994/06/25 00:43:46 aoki Exp
   *
   * BufferAlloc() -- lookup a buffer in the buffer table.  If
   *	it isn't there add it, but do not read it into memory.
--- 2,8 ----
   * bufmgr.c -- buffer manager interface routines
   *
   * Identification:
!  *	$Header: /usr/local/devel/postgres/src/backend/storage/buffer/RCS/bufmgr.c,v 1.84 1994/07/19 01:39:20 aoki Exp $
   *
   * BufferAlloc() -- lookup a buffer in the buffer table.  If
   *	it isn't there add it, but do not read it into memory.
***************
*** 160,171 ****
      if (BufferIsValid(buffer)) {
          bufHdr = BufferGetBufferDescriptor(buffer);
  	lrelId = RelationGetLRelId(relation);
  	if (bufHdr->tag.blockNum == blockNumber &&
  	    bufHdr->tag.relId.relId == lrelId.relId &&
! 	    bufHdr->tag.relId.dbId == lrelId.dbId)
! 	    return buffer;
!       }
!     return(ReadBuffer(relation,blockNumber));
  }
  
  /*
--- 160,175 ----
      if (BufferIsValid(buffer)) {
          bufHdr = BufferGetBufferDescriptor(buffer);
  	lrelId = RelationGetLRelId(relation);
+ 	SpinAcquire(BufMgrLock);
  	if (bufHdr->tag.blockNum == blockNumber &&
  	    bufHdr->tag.relId.relId == lrelId.relId &&
! 	    bufHdr->tag.relId.dbId == lrelId.dbId) {
! 	    SpinRelease(BufMgrLock);
! 	    return(buffer);
! 	}
! 	return(ReadBufferWithBufferLock(relation, blockNumber, true));
!     }
!     return(ReadBuffer(relation, blockNumber));
  }
  
  /*
***************
*** 192,197 ****
--- 196,207 ----
      return ReadBufferWithBufferLock(reln, blockNum, false);
  }
  
+ /*
+  * is_userbuffer
+  *
+  * XXX caller must have already acquired BufMgrLock
+  */
+ static
  bool
  is_userbuffer(buffer)
  Buffer buffer;
***************
*** 214,221 ****
  
      buffer = ReadBufferWithBufferLock(reln, blockNum, false);
      if (ShowPinTrace && is_userbuffer(buffer)) {
! 	BufferDesc *buf;
! 	buf = BufferGetBufferDescriptor(buffer);
  	fprintf(stderr, "PIN(RD) %d relname = %.*s, blockNum = %d, \
  refcount = %d, file: %s, line: %d\n",
  		buffer, NAMEDATALEN, &(buf->sb_relname), buf->tag.blockNum,
--- 224,231 ----
  
      buffer = ReadBufferWithBufferLock(reln, blockNum, false);
      if (ShowPinTrace && is_userbuffer(buffer)) {
! 	BufferDesc *buf = BufferGetBufferDescriptor(buffer);
! 
  	fprintf(stderr, "PIN(RD) %d relname = %.*s, blockNum = %d, \
  refcount = %d, file: %s, line: %d\n",
  		buffer, NAMEDATALEN, &(buf->sb_relname), buf->tag.blockNum,
***************
*** 230,238 ****
   *	the buffer lock has already been held. this
   *	is yet another effort to reduce the number of
   *	semops in the system.
-  *
-  *  This routine locks the buffer pool before calling BufferAlloc to
-  *  avoid two semops.
   */
  
  Buffer
--- 240,245 ----
***************
*** 331,336 ****
--- 338,345 ----
   *	read it.
   *
   * Returns: descriptor for buffer
+  *
+  * When this routine returns, the BufMgrLock is guaranteed NOT be held.
   */
  BufferDesc *
  BufferAlloc(reln, blockNum, foundPtr, bufferLockHeld)
***************
*** 410,423 ****
     */
    inProgress = FALSE;
    for (buf = (BufferDesc *) NULL; buf == (BufferDesc *) NULL; ) {
        buf = GetFreeBuffer();
!       if (! buf) {
! 	  /* out of free buffers.  In trouble now. */
! 	  /* XXX actually, GetFreeBuffer already aborted us... */
! 	  SpinRelease(BufMgrLock);
! 	  return((BufferDesc *) NULL);
!       }
!       
        /*
         * There should be exactly one pin on the buffer after
         * it is allocated -- ours.  If it had a pin it wouldn't
--- 419,428 ----
     */
    inProgress = FALSE;
    for (buf = (BufferDesc *) NULL; buf == (BufferDesc *) NULL; ) {
+ 
+       /* GetFreeBuffer will abort if it can't find a free buffer */
        buf = GetFreeBuffer();
! 
        /*
         * There should be exactly one pin on the buffer after
         * it is allocated -- ours.  If it had a pin it wouldn't
***************
*** 459,468 ****
  	   * you on machines that don't have spinlocks.  If you don't
  	   * operate with much concurrency, well...
  	   */
! #ifndef OPTIMIZE_SINGLE
! 	  SpinRelease(BufMgrLock);
! #endif /* OPTIMIZE_SINGLE */
! 	  (void) BufferReplace(buf);
  	  BufferFlushCount++;
  #ifndef OPTIMIZE_SINGLE
  	  SpinAcquire(BufMgrLock);
--- 464,470 ----
  	   * you on machines that don't have spinlocks.  If you don't
  	   * operate with much concurrency, well...
  	   */
! 	  (void) BufferReplace(buf, true);
  	  BufferFlushCount++;
  #ifndef OPTIMIZE_SINGLE
  	  SpinAcquire(BufMgrLock);
***************
*** 589,596 ****
      }
      bufHdr = BufferGetBufferDescriptor(buffer);
  
-     Assert(bufHdr->refcount > 0);
      SpinAcquire(BufMgrLock);
      bufHdr->flags |= BM_DIRTY; 
      UnpinBuffer(bufHdr);
      SpinRelease(BufMgrLock);
--- 591,598 ----
      }
      bufHdr = BufferGetBufferDescriptor(buffer);
  
      SpinAcquire(BufMgrLock);
+     Assert(bufHdr->refcount > 0);
      bufHdr->flags |= BM_DIRTY; 
      UnpinBuffer(bufHdr);
      SpinRelease(BufMgrLock);
***************
*** 671,688 ****
      return(STATUS_ERROR);
    }
    bufHdr = BufferGetBufferDescriptor(buffer);
-   Assert(bufHdr->refcount > 0);
  
    if (LateWrite) {
      SpinAcquire(BufMgrLock); 
      bufHdr->flags |= BM_DIRTY; 
      UnpinBuffer(bufHdr);
      SpinRelease(BufMgrLock); 
    } else {
!     BufferReplace(bufHdr);
    }
  
- 
    return(STATUS_OK);
  } 
  
--- 673,689 ----
      return(STATUS_ERROR);
    }
    bufHdr = BufferGetBufferDescriptor(buffer);
  
    if (LateWrite) {
      SpinAcquire(BufMgrLock); 
+     Assert(bufHdr->refcount > 0);
      bufHdr->flags |= BM_DIRTY; 
      UnpinBuffer(bufHdr);
      SpinRelease(BufMgrLock); 
    } else {
!     BufferReplace(bufHdr, false);
    }
  
    return(STATUS_OK);
  } 
  
***************
*** 689,694 ****
--- 690,700 ----
  
  /*
   * FlushBuffer -- like WriteBuffer, but force the page to disk.
+  *
+  * 'buffer' is known to be dirty/pinned, so there should not be a
+  * problem reading the BufferDesc members without the BufMgrLock
+  * (nobody should be able to change tags, flags, etc. out from under
+  * us).
   */
  FlushBuffer(buffer)
  Buffer	buffer;
***************
*** 706,739 ****
  
    bufHdr = BufferGetBufferDescriptor(buffer);
  
!   /*
!    *  If the relation is not in our private cache, we don't bother trying
!    *  to instantiate it.  Instead, we call the storage manager routine that
!    *  does a blind write.  If we can get the reldesc, then we use the standard
!    *  write routine interface.
!    */
! 
!   bufdb = bufHdr->tag.relId.dbId;
!   bufrel = bufHdr->tag.relId.relId;
! 
!   if (bufdb == MyDatabaseId || bufdb == (OID) NULL)
!       reln = RelationIdCacheGetRelation(bufrel);
!   else
!       reln = (Relation) NULL;
! 
!   if (reln != (Relation) NULL) {
!       status = smgrflush(bufHdr->bufsmgr, reln, bufHdr->tag.blockNum,
! 			 (char *) MAKE_PTR(bufHdr->data));
!   } else {
! 
!       /* blind write always flushes */
!       status = smgrblindwrt(bufHdr->bufsmgr, &bufHdr->sb_dbname,
! 			    &bufHdr->sb_relname, bufdb, bufrel,
! 			    bufHdr->tag.blockNum,
! 			    (char *) MAKE_PTR(bufHdr->data));
!   }
! 
!   if (status == SM_FAIL) {
        elog(WARN, "FlushBuffer: cannot flush %d for %16s", bufHdr->tag.blockNum,
  		 reln->rd_rel->relname);
        /* NOTREACHED */
--- 712,718 ----
  
    bufHdr = BufferGetBufferDescriptor(buffer);
  
!   if (!BufferReplace(bufHdr, false)) {
        elog(WARN, "FlushBuffer: cannot flush %d for %16s", bufHdr->tag.blockNum,
  		 reln->rd_rel->relname);
        /* NOTREACHED */
***************
*** 823,829 ****
  BufferAcquire(bufHdr)
  BufferDesc	*bufHdr;
  {
- 
    SpinAcquire(BufMgrLock);
    PinBuffer(bufHdr);
    SpinRelease(BufMgrLock);
--- 802,807 ----
***************
*** 843,852 ****
    }
    bufHdr = BufferGetBufferDescriptor(buffer);
  
    /* like we said -- already pinned */
    Assert(bufHdr->refcount);
- 
-   SpinAcquire(BufMgrLock);
    PinBuffer(bufHdr);
    SpinRelease(BufMgrLock);
    return (TRUE);
--- 821,829 ----
    }
    bufHdr = BufferGetBufferDescriptor(buffer);
  
+   SpinAcquire(BufMgrLock);
    /* like we said -- already pinned */
    Assert(bufHdr->refcount);
    PinBuffer(bufHdr);
    SpinRelease(BufMgrLock);
    return (TRUE);
***************
*** 879,886 ****
    BufferDesc *bufHdr;
    int status;
  
    for (i=0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++) {
!       if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY)) {
  	  bufdb = bufHdr->tag.relId.dbId;
  	  bufrel = bufHdr->tag.relId.relId;
  	  if (bufdb == MyDatabaseId || bufdb == (OID) 0) {
--- 856,864 ----
    BufferDesc *bufHdr;
    int status;
  
+   SpinAcquire(BufMgrLock);
    for (i=0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++) {
!      if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY)) {
  	  bufdb = bufHdr->tag.relId.dbId;
  	  bufrel = bufHdr->tag.relId.relId;
  	  if (bufdb == MyDatabaseId || bufdb == (OID) 0) {
***************
*** 892,897 ****
--- 870,878 ----
  	       *  we did find it, use the standard interface.
  	       */
  
+ #ifndef OPTIMIZE_SINGLE
+ 	      SpinRelease(BufMgrLock);
+ #endif /* OPTIMIZE_SINGLE */
  	      if (reln == (Relation) NULL) {
  		  status = smgrblindwrt(bufHdr->bufsmgr, &bufHdr->sb_dbname,
  					&bufHdr->sb_relname, bufdb, bufrel,
***************
*** 902,907 ****
--- 883,891 ----
  				     bufHdr->tag.blockNum,
  				     (char *) MAKE_PTR(bufHdr->data));
  	      }
+ #ifndef OPTIMIZE_SINGLE
+ 	      SpinAcquire(BufMgrLock);
+ #endif /* OPTIMIZE_SINGLE */
  
  	      if (status == SM_FAIL) {
  		  elog(WARN, "cannot write %d for %16s",
***************
*** 914,919 ****
--- 898,904 ----
  	  }
        }
    }
+   SpinRelease(BufMgrLock);
  }
  
  
***************
*** 1208,1213 ****
--- 1193,1199 ----
      Buffer      buffer;
  {
      Assert(BufferIsValid(buffer));
+     /* XXX should be a critical section */
      return (BufferGetBufferDescriptor(buffer)->tag.blockNum);
  }
  
***************
*** 1219,1224 ****
--- 1205,1211 ----
  
      Assert(BufferIsValid(buffer));
  
+     /* XXX should be a critical section */
      relation = RelationIdGetRelation(LRelIdGetRelationId
                  (BufferGetBufferDescriptor(buffer)->tag.relId));
  
***************
*** 1265,1272 ****
  
  #endif /* !NO_ASSERT_CHECKING */
  
! BufferReplace(bufHdr)
      BufferDesc 	*bufHdr;
  {
      int		blockSize;
      int		blockNum;
--- 1252,1267 ----
  
  #endif /* !NO_ASSERT_CHECKING */
  
! /*
!  * BufferReplace
!  *
!  * Flush the buffer corresponding to 'bufHdr'
!  *
!  * Assumes that the BufMgrLock has NOT been acquired.
!  */
! BufferReplace(bufHdr, bufferLockHeld)
      BufferDesc 	*bufHdr;
+     bool bufferLockHeld;
  {
      int		blockSize;
      int		blockNum;
***************
*** 1275,1280 ****
--- 1270,1278 ----
      ObjectId	bufdb, bufrel;
      int		status;
  
+     if (!bufferLockHeld)
+ 	SpinAcquire(BufMgrLock);
+ 
      blockSize = BLOCKSZ(bufHdr);
      blockNum = bufHdr->tag.blockNum;
  
***************
*** 1292,1297 ****
--- 1290,1297 ----
      else
  	reln = (Relation) NULL;
  
+     SpinRelease(BufMgrLock);
+ 
      if (reln != (Relation) NULL) {
  	status = smgrflush(bufHdr->bufsmgr, reln, bufHdr->tag.blockNum,
  			   (char *) MAKE_PTR(bufHdr->data));
***************
*** 1311,1330 ****
  }
  
  /**************************************************
-   BufferIsDirty
- 
-  **************************************************/
- 
- bool
- BufferIsDirty(buffer)
-     Buffer buffer;
- {
-     return (bool)
-         (BufferGetBufferDescriptor(buffer)->flags & BM_DIRTY);
- }
- 
- 
- /**************************************************
    BufferIsInvalid
  
   **************************************************/
--- 1311,1316 ----
***************
*** 1396,1413 ****
  Relation tempreldesc;
  {
      register int i;
      BufferDesc *buf;
  
      for (i=1; i<=NBuffers; i++) {
  	buf = BufferGetBufferDescriptor(i);
!         if (BufferIsDirty(i) &&
              (buf->tag.relId.dbId == MyDatabaseId) &&
              (buf->tag.relId.relId == tempreldesc->rd_id)) {
              buf->flags &= ~BM_DIRTY;
!             if (!(buf->flags & BM_FREE))
!                ReleaseBuffer(i);
!         }
!      }
  }
  
  /* ---------------------------------------------------------------------
--- 1382,1409 ----
  Relation tempreldesc;
  {
      register int i;
+     int holding = 0;
      BufferDesc *buf;
  
      for (i=1; i<=NBuffers; i++) {
  	buf = BufferGetBufferDescriptor(i);
! 	if (!holding) {
! 	    SpinAcquire(BufMgrLock);
! 	    holding = 1;
! 	}
!         if ((buf->flags & BM_DIRTY) &&
              (buf->tag.relId.dbId == MyDatabaseId) &&
              (buf->tag.relId.relId == tempreldesc->rd_id)) {
              buf->flags &= ~BM_DIRTY;
!             if (!(buf->flags & BM_FREE)) {
! 		SpinRelease(BufMgrLock);
! 		holding = 0;
! 		ReleaseBuffer(i);
! 	    }
! 	}
!     }
!     if (holding)
! 	SpinRelease(BufMgrLock);
  }
  
  /* ---------------------------------------------------------------------
***************
*** 1429,1440 ****
      register int i;
      BufferDesc *buf;
  
      for (i=1; i<=NBuffers; i++) {
  	buf = BufferGetBufferDescriptor(i);
          if ((buf->tag.relId.dbId == dbid) && (buf->flags & BM_DIRTY)) {
              buf->flags &= ~BM_DIRTY;
          }
!      }
  }
  
  /* -----------------------------------------------------------------
--- 1425,1438 ----
      register int i;
      BufferDesc *buf;
  
+     SpinAcquire(BufMgrLock);
      for (i=1; i<=NBuffers; i++) {
  	buf = BufferGetBufferDescriptor(i);
          if ((buf->tag.relId.dbId == dbid) && (buf->flags & BM_DIRTY)) {
              buf->flags &= ~BM_DIRTY;
          }
!     }
!     SpinRelease(BufMgrLock);
  }
  
  /* -----------------------------------------------------------------
***************
*** 1451,1456 ****
--- 1449,1455 ----
      int i;
      BufferDesc *buf = BufferDescriptors;
  
+     SpinAcquire(BufMgrLock);
      for (i = 0; i < NBuffers; ++i, ++buf) {
  	elog(NOTICE, "[%02d] (freeNext=%d, freePrev=%d, relname=%.*s, \
  blockNum=%d, flags=0x%x, refcount=%d %d)",
***************
*** 1458,1481 ****
  	     buf->tag.blockNum, buf->flags,
  	     buf->refcount, PrivateRefCount[i]);
      }
  }
  
  void
- GetPageAddr(bufno)
- 	long bufno;
- {
- 	long p;
- 
- 	p = ShmemBase + BufferDescriptors[bufno].data;
- 	printf("0x%lx (%ld)\n", p, p);
- }
- 
- void
  PrintPinnedBufs()
  {
      int i;
      BufferDesc *buf = BufferDescriptors;
  
      for (i = 0; i < NBuffers; ++i, ++buf) {
  	if (PrivateRefCount[i] > 0)
  	    elog(NOTICE, "[%02d] (freeNext=%d, freePrev=%d, relname=%.*s, \
--- 1457,1472 ----
  	     buf->tag.blockNum, buf->flags,
  	     buf->refcount, PrivateRefCount[i]);
      }
+     SpinRelease(BufMgrLock);
  }
  
  void
  PrintPinnedBufs()
  {
      int i;
      BufferDesc *buf = BufferDescriptors;
  
+     SpinAcquire(BufMgrLock);
      for (i = 0; i < NBuffers; ++i, ++buf) {
  	if (PrivateRefCount[i] > 0)
  	    elog(NOTICE, "[%02d] (freeNext=%d, freePrev=%d, relname=%.*s, \
***************
*** 1483,1489 ****
  		 i, buf->freeNext, buf->freePrev, NAMEDATALEN, &(buf->sb_relname),
  		 buf->tag.blockNum, buf->flags,
  		 buf->refcount, PrivateRefCount[i]);
!      }
  }
  
  /* -----------------------------------------------------
--- 1474,1481 ----
  		 i, buf->freeNext, buf->freePrev, NAMEDATALEN, &(buf->sb_relname),
  		 buf->tag.blockNum, buf->flags,
  		 buf->refcount, PrivateRefCount[i]);
!     }
!     SpinRelease(BufMgrLock);
  }
  
  /* -----------------------------------------------------
*** postgres-v4r2/./src/backend/storage/buffer/order.c	Mon Aug  9 18:46:51 1993
--- postgres/./src/backend/storage/buffer/order.c	Sat Jul 16 03:13:50 1994
***************
*** 5,11 ****
  
  #include "tmp/c.h"
  
! RcsId("/usr/local/devel/postgres-v4r2/src/backend/storage/buffer/RCS/order.c,v 1.13 1993/08/10 01:46:51 marc Exp");
  
  #include "utils/log.h"
  
--- 5,11 ----
  
  #include "tmp/c.h"
  
! RcsId("$Header: /usr/local/devel/postgres/src/backend/storage/buffer/RCS/order.c,v 1.14 1994/07/16 10:09:26 aoki Exp $");
  
  #include "utils/log.h"
  
***************
*** 61,90 ****
  	return(ret);
  }
  
- 
  /*
-  *	bwinit
-  *
-  *	Initialize the data structures needed for buffer ordering.
-  */
- 
- bwinit()
- {
- 	register int	i;
- 
- 	adjlist = (Stack**)malloc(NBuffers * sizeof(Stack*));
- 	datlist = (BufferDesc**)malloc(NBuffers * sizeof(BufferDesc*));
- 	used = (long *)malloc(NBuffers * sizeof(int));
- 
- 	for (i = 0; i < NBuffers; i++) {
- 		adjlist[i] = (Stack *) NULL;
- 		datlist[i] = (BufferDesc *) NULL;
- 		used[i] = 0;
- 	}
- }
- 
- 
- /*
   *	bworder
   *
   *	Enter two buffers into the partial ordering.
--- 61,67 ----
***************
*** 130,273 ****
  	/* Save the successor in the predecessor's adjacency list */
  	bs_push(after, &adjlist[before]);
  	used[before] = used[after] = 1;
- 	return(0);
- }
- 
- /*
-  *	bwsort
-  *
-  *	Determines which buffers must be written before 'item', given the
-  *	partial order (DAG) created by calls to bw_before().
-  *
-  *	Returns an array of size NBuffers which contains the buffer numbers
-  *	in the order in which they must be written (up to 'item').
-  *
-  *	Cannot cope with cycles.
-  *
-  *	Uses the O(n+e) topological sort from Mellhorn, Vol. I.
-  */
- 
- BufferDesc **
- bwsort(item)
- 	BufferDesc	*item;
- {
- 	register int		i;
- 	int			count = 0, active_bufs = 0;
- 	register Stack		*sp;
- 	Stack			*zeroindeg = (Stack *) NULL;
- 	long			*indeg;
- 	static BufferDesc	**ret;
- 
- 
- 	indeg = (long *)malloc(NBuffers * sizeof(long));
- 	ret = (BufferDesc**)malloc(NBuffers * sizeof(BufferDesc*));
- 	for (i = 0; i < NBuffers; i++) {
- 		ret[i] = (BufferDesc *) NULL;
- 		indeg[i] = 0;
- 	}
- 
- 	/* Calculate indegrees for each vertex */
- 	for (i = 0; i < NBuffers; i++)
- 		for (sp = adjlist[i]; sp != (Stack *) NULL; sp = sp->next)
- 			indeg[sp->datum]++;
- 
- 	/*
- 	 * Push all 'root' vertices onto the stack.
- 	 * While we do this, check to see if 'item' has an indegree of 0.
- 	 * 	If so, we don't have to do the topological sort.
- 	 */
- 	for (i = 0; i < NBuffers; i++)
- 		if (indeg[i] == 0)
- 			if (datlist[i] == item) {	/* no need to sort */
- 				ret[0] = item;
- 				free((char*)indeg);
- 				free((char*)ret);
- 				return(ret);
- 			} else
- 				bs_push(i, &zeroindeg);
- 
- 	/*
- 	 * Perform the topological sort.
- 	 */
- 	while (zeroindeg != (Stack *) NULL) {
- 		if ((i = bs_pop(&zeroindeg)) < 0) {
- 			elog(WARN, "bwsort: stack error");
- 			free((char*)indeg);
- 			free((char*)ret);
- 			return((BufferDesc **) NULL);
- 		}
- 		if (used[i])			/* ignore unused buffers */
- 			ret[count++] = datlist[i];
- 		for (sp = adjlist[i]; sp != (Stack *) NULL; sp = sp->next) {
- 			indeg[sp->datum]--;
- 			if (indeg[sp->datum] == 0)
- 				bs_push(sp->datum, &zeroindeg);
- 		}
- 	}
- 
- 	/* Either 'item' is last or we have some kind of error */
- 	for (i = 0; i < NBuffers; i++)
- 		active_bufs += used[i];
- 	if (count != active_bufs) {
- 		elog(WARN, "bwsort: cycle in buffer ordering!");
- 		free((char*)indeg);
- 		free((char*)ret);
- 		return((BufferDesc **) NULL);
- 	}
- 
- 	free((char*)indeg);
- 	free((char*)ret);
- 	return(ret);
- }
- 
- 
- /*
-  *	bwremove
-  *
-  *	Remove the argument item from the ordering data structures.
-  */
- 
- bwremove(nitems, items)
- 	int		nitems;
- 	BufferDesc	*items[];
- {
- 	register Stack	*p;
- 	register int	i, j;
- 	long		*remove;
- 
- 	remove = (long *)malloc(NBuffers * sizeof(long));
- 	if (nitems < 0 || nitems > NBuffers) {
- 		elog(WARN, "bwremove: bad nitems %d", nitems);
- 		free((char*)remove);
- 		return(-1);
- 	}
- 
- 	/* Mark off the items in 'datlist' to remove */
- 	for (i = 0; i < nitems; i++) 
- 		for (j = 0; j < NBuffers; j++)
- 			if (items[i] == datlist[j])
- 				remove[j] = 1;
- 	for (i = 0; i < nitems; i++)
- 		if (remove[i] != 1) {
- 			elog(WARN, "bwremove: ordering corrupted");
- 			free((char*)remove);
- 			return(-1);
- 		}
- 
- 	/* Remove everything in 'adjlist' having to do with those items */
- 	for (i = 0; i < NBuffers; i++) {
- 		if ((p = adjlist[i]) == (Stack *) NULL)
- 			continue;
- 		else if (p->next == (Stack *) NULL)
- 			if (remove[p->datum])
- 				adjlist[i] = (Stack *) NULL;
- 		else
- 			for (; p->next != (Stack *) NULL;
- 			     p = p->next)
- 				if (remove[p->next->datum])
- 					p->next = p->next->next;
- 		used[i] = 0;
- 	}
- 	free((char*)remove);
  	return(0);
  }
--- 107,111 ----
*** postgres-v4r2/./src/backend/storage/ipc/s_lock.c	Fri Jun 24 17:43:46 1994
--- postgres/./src/backend/storage/ipc/s_lock.c	Mon Jul 18 18:41:41 1994
***************
*** 28,34 ****
   *	manual for POWER in any case.
   *
   *   IDENTIFICATION
!  *	/usr/local/devel/postgres-v4r2/src/backend/storage/ipc/RCS/s_lock.c,v 1.13 1994/06/25 00:43:46 aoki Exp
   * ----------------------------------------------------------------
   */
  
--- 28,34 ----
   *	manual for POWER in any case.
   *
   *   IDENTIFICATION
!  *	$Header: /usr/local/devel/postgres/src/backend/storage/ipc/RCS/s_lock.c,v 1.14 1994/07/19 01:41:29 aoki Exp $
   * ----------------------------------------------------------------
   */
  
***************
*** 35,55 ****
  #include "storage/ipci.h"
  #include "storage/ipc.h"
  
! RcsId("/usr/local/devel/postgres-v4r2/src/backend/storage/ipc/RCS/s_lock.c,v 1.13 1994/06/25 00:43:46 aoki Exp");
  
  #if defined(HAS_TEST_AND_SET)
  
  /*
   * OSF/1 (Alpha AXP)
-  * Solaris 2
   *
!  * Note that slock_t on the Alpha AXP is long instead of char
   * (see storage/ipc.h).
   */
  
! #if defined(PORTNAME_alpha) || \
!     defined(PORTNAME_sparc_solaris)
  
  /* defined in port/.../tas.s */
  extern int tas ARGS((slock_t *lock));
  
--- 35,86 ----
  #include "storage/ipci.h"
  #include "storage/ipc.h"
  
! RcsId("$Header: /usr/local/devel/postgres/src/backend/storage/ipc/RCS/s_lock.c,v 1.14 1994/07/19 01:41:29 aoki Exp $");
  
  #if defined(HAS_TEST_AND_SET)
  
  /*
   * OSF/1 (Alpha AXP)
   *
!  * Note that slock_t on the Alpha AXP is msemaphore instead of char
   * (see storage/ipc.h).
   */
  
! #if defined(PORTNAME_alpha)
  
+ S_LOCK(lock)
+     slock_t *lock;
+ {
+     while (msem_lock(lock, MSEM_IF_NOWAIT) < 0)
+ 	;
+ }
+ 
+ S_UNLOCK(lock)
+     slock_t *lock;
+ {
+     (void) msem_unlock(lock, 0);
+ }
+ 
+ S_INIT_LOCK(lock)
+     slock_t *lock;
+ {
+     (void) msem_init(lock, MSEM_UNLOCKED);
+ }
+ 
+ S_LOCK_FREE(lock)
+     slock_t *lock;
+ {
+     return(lock->msem_state ? 0 : 1);
+ }
+ 
+ #endif /* PORTNAME_alpha */
+ 
+ /*
+  * Solaris 2
+  */
+ 
+ #if defined(PORTNAME_sparc_solaris)
+ 
  /* defined in port/.../tas.s */
  extern int tas ARGS((slock_t *lock));
  
***************
*** 72,78 ****
      S_UNLOCK(lock);
  }
  
! #endif /* PORTNAME_alpha */
  
  /*
   * AIX (POWER)
--- 103,109 ----
      S_UNLOCK(lock);
  }
  
! #endif /* PORTNAME_sparc_solaris */
  
  /*
   * AIX (POWER)

==============================================================================
   To add/remove yourself to/from the POSTGRES mailing list: send mail with 
   the subject line ADD or DEL to "postgres-request@postgres.Berkeley.EDU"

   If this fails, send mail to "post_questions@postgres.Berkeley.EDU" and
   a human will deal with it.  DO NOT post to the "postgres" mailing list.
==============================================================================
