diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 1abb938fdf8d6be76a31e15bbfa47ae8dea07b31..e9f69476283118541461e860696caf3a697c974f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.143 2002/07/30 16:08:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.144 2002/08/06 02:36:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1155,6 +1155,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 	pgstat_count_heap_insert(&relation->pgstat_info);
 
 	/* XLOG stuff */
+	if (!relation->rd_istemp)
 	{
 		xl_heap_insert xlrec;
 		xl_heap_header xlhdr;
@@ -1204,6 +1205,12 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
 		PageSetLSN(page, recptr);
 		PageSetSUI(page, ThisStartUpID);
 	}
+	else
+	{
+		/* No XLOG record, but still need to flag that XID exists on disk */
+		MyXactMadeTempRelUpdate = true;
+	}
+
 	END_CRIT_SECTION();
 
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
@@ -1323,12 +1330,15 @@ l1:
 	}
 
 	START_CRIT_SECTION();
+
 	/* store transaction information of xact deleting the tuple */
 	tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
 							 HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
 	HeapTupleHeaderSetXmax(tp.t_data, GetCurrentTransactionId());
 	HeapTupleHeaderSetCmax(tp.t_data, cid);
+
 	/* XLOG stuff */
+	if (!relation->rd_istemp)
 	{
 		xl_heap_delete xlrec;
 		XLogRecPtr	recptr;
@@ -1351,12 +1361,17 @@ l1:
 		PageSetLSN(dp, recptr);
 		PageSetSUI(dp, ThisStartUpID);
 	}
+	else
+	{
+		/* No XLOG record, but still need to flag that XID exists on disk */
+		MyXactMadeTempRelUpdate = true;
+	}
+
 	END_CRIT_SECTION();
 
 	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
 
 #ifdef TUPLE_TOASTER_ACTIVE
-
 	/*
 	 * If the relation has toastable attributes, we need to delete no
 	 * longer needed items there too.  We have to do this before
@@ -1659,6 +1674,7 @@ l2:
 	oldtup.t_data->t_ctid = newtup->t_self;
 
 	/* XLOG stuff */
+	if (!relation->rd_istemp)
 	{
 		XLogRecPtr	recptr = log_heap_update(relation, buffer, oldtup.t_self,
 											 newbuf, newtup, false);
@@ -1671,6 +1687,11 @@ l2:
 		PageSetLSN(BufferGetPage(buffer), recptr);
 		PageSetSUI(BufferGetPage(buffer), ThisStartUpID);
 	}
+	else
+	{
+		/* No XLOG record, but still need to flag that XID exists on disk */
+		MyXactMadeTempRelUpdate = true;
+	}
 
 	END_CRIT_SECTION();
 
@@ -1927,6 +1948,9 @@ log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen)
 	XLogRecPtr	recptr;
 	XLogRecData rdata[3];
 
+	/* Caller should not call me on a temp relation */
+	Assert(!reln->rd_istemp);
+
 	xlrec.node = reln->rd_node;
 	xlrec.block = BufferGetBlockNumber(buffer);
 	rdata[0].buffer = InvalidBuffer;
@@ -1978,6 +2002,9 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
 	Page		page = BufferGetPage(newbuf);
 	uint8		info = (move) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE;
 
+	/* Caller should not call me on a temp relation */
+	Assert(!reln->rd_istemp);
+
 	xlrec.target.node = reln->rd_node;
 	xlrec.target.tid = from;
 	xlrec.newtid = newtup->t_self;
@@ -2012,7 +2039,8 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
 			xid[0] = HeapTupleHeaderGetXmax(newtup->t_data);
 		xid[1] = HeapTupleHeaderGetXmin(newtup->t_data);
 		memcpy((char *) &xlhdr + hsize,
-		       (char *) xid,            2 * sizeof(TransactionId));
+		       (char *) xid,
+			   2 * sizeof(TransactionId));
 		hsize += 2 * sizeof(TransactionId);
 	}
 	rdata[2].buffer = newbuf;
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 602ad748d9be9b2a8493f00794e759430daf80a9..67eb4ad7e244ba2055033ee7f1aae10c6845b93d 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Id: hio.c,v 1.45 2002/06/20 20:29:25 momjian Exp $
+ *	  $Id: hio.c,v 1.46 2002/08/06 02:36:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,6 +102,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
 	Size		pageFreeSpace;
 	BlockNumber targetBlock,
 				otherBlock;
+	bool		needLock;
 
 	len = MAXALIGN(len);		/* be conservative */
 
@@ -231,9 +232,12 @@ RelationGetBufferForTuple(Relation relation, Size len,
 	 *
 	 * We have to use a lock to ensure no one else is extending the rel at
 	 * the same time, else we will both try to initialize the same new
-	 * page.
+	 * page.  We can skip locking for new or temp relations, however,
+	 * since no one else could be accessing them.
 	 */
-	if (!relation->rd_myxactonly)
+	needLock = !(relation->rd_isnew || relation->rd_istemp);
+
+	if (needLock)
 		LockPage(relation, 0, ExclusiveLock);
 
 	/*
@@ -249,7 +253,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
 	 * Release the file-extension lock; it's now OK for someone else to
 	 * extend the relation some more.
 	 */
-	if (!relation->rd_myxactonly)
+	if (needLock)
 		UnlockPage(relation, 0, ExclusiveLock);
 
 	/*
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 2945cf3458cb567ba7dedb522bb0ccf41c9c8bcd..1c09af2b30840eed8df8c1dea10ed862b1cb859d 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.33 2002/07/20 05:16:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.34 2002/08/06 02:36:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -915,7 +915,7 @@ toast_save_datum(Relation rel, Datum value)
 		 */
 		idxres = index_insert(toastidx, t_values, t_nulls,
 							  &(toasttup->t_self),
-							  toastrel, toastidx->rd_uniqueindex);
+							  toastrel, toastidx->rd_index->indisunique);
 		if (idxres == NULL)
 			elog(ERROR, "Failed to insert index entry for TOAST tuple");
 
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index c0190859b7bfef787023bc09dc4ee6ff443fcd45..16d63e03c99e517e415dc989d84afefe82717b50 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.94 2002/07/02 05:48:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.95 2002/08/06 02:36:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -623,8 +623,11 @@ _bt_insertuple(Relation rel, Buffer buf,
 	BTPageOpaque pageop = (BTPageOpaque) PageGetSpecialPointer(page);
 
 	START_CRIT_SECTION();
+
 	_bt_pgaddtup(rel, page, itemsz, btitem, newitemoff, "page");
+
 	/* XLOG stuff */
+	if (!rel->rd_istemp)
 	{
 		xl_btree_insert xlrec;
 		uint8		flag = XLOG_BTREE_INSERT;
@@ -866,6 +869,9 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
 	 * NO ELOG(ERROR) till right sibling is updated.
 	 */
 	START_CRIT_SECTION();
+
+	/* XLOG stuff */
+	if (!rel->rd_istemp)
 	{
 		xl_btree_split xlrec;
 		int			flag = (newitemonleft) ?
@@ -891,7 +897,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
 		BlockIdSet(&(xlrec.rightblk), ropaque->btpo_next);
 
 		/*
-		 * Dirrect access to page is not good but faster - we should
+		 * Direct access to page is not good but faster - we should
 		 * implement some new func in page API.
 		 */
 		xlrec.leftlen = ((PageHeader) leftpage)->pd_special -
@@ -1352,6 +1358,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
 	(metad->btm_level)++;
 
 	/* XLOG stuff */
+	if (!rel->rd_istemp)
 	{
 		xl_btree_newroot xlrec;
 		XLogRecPtr	recptr;
@@ -1366,7 +1373,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
 		rdata[0].next = &(rdata[1]);
 
 		/*
-		 * Dirrect access to page is not good but faster - we should
+		 * Direct access to page is not good but faster - we should
 		 * implement some new func in page API.
 		 */
 		rdata[1].buffer = InvalidBuffer;
@@ -1388,6 +1395,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
 		PageSetLSN(rpage, recptr);
 		PageSetSUI(rpage, ThisStartUpID);
 	}
+
 	END_CRIT_SECTION();
 
 	/* write and let go of metapage buffer */
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 386cb6a07a55e2600ff9d25d262d053f0603b12e..110de69406669b2c9e6a8e6350b5acbb55144172 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.57 2002/06/20 20:29:25 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.58 2002/08/06 02:36:33 tgl Exp $
  *
  *	NOTES
  *	   Postgres btree pages look like ordinary relation pages.	The opaque
@@ -173,6 +173,7 @@ _bt_getroot(Relation rel, int access)
 			rootopaque->btpo_flags |= (BTP_LEAF | BTP_ROOT);
 
 			/* XLOG stuff */
+			if (!rel->rd_istemp)
 			{
 				xl_btree_newroot xlrec;
 				XLogRecPtr	recptr;
@@ -187,7 +188,8 @@ _bt_getroot(Relation rel, int access)
 				rdata.next = NULL;
 
 				recptr = XLogInsert(RM_BTREE_ID,
-						   XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF, &rdata);
+									XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF,
+									&rdata);
 
 				PageSetLSN(rootpage, recptr);
 				PageSetSUI(rootpage, ThisStartUpID);
@@ -457,6 +459,7 @@ _bt_itemdel(Relation rel, Buffer buf, ItemPointer tid)
 	PageIndexTupleDelete(page, offno);
 
 	/* XLOG stuff */
+	if (!rel->rd_istemp)
 	{
 		xl_btree_delete xlrec;
 		XLogRecPtr	recptr;
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 3a992f6ccfe44b9169cc879baaf9d9f32a285026..c9b60daef563cc764a6ef6429ad3d6fb92fd9325 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.129 2002/08/02 22:36:05 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.130 2002/08/06 02:36:33 tgl Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -505,44 +505,32 @@ AtStart_Memory(void)
  * ----------------------------------------------------------------
  */
 
-/* --------------------------------
+/*
  *		RecordTransactionCommit
- *
- *		Note: the two calls to BufferManagerFlush() exist to ensure
- *			  that data pages are written before log pages.  These
- *			  explicit calls should be replaced by a more efficient
- *			  ordered page write scheme in the buffer manager
- *			  -cim 3/18/90
- * --------------------------------
  */
 void
 RecordTransactionCommit(void)
 {
-	TransactionId xid;
-	bool		leak;
-
-	leak = BufferPoolCheckLeak();
-
-	xid = GetCurrentTransactionId();
-
 	/*
-	 * We only need to log the commit in xlog and clog if the transaction made
-	 * any transaction-controlled XLOG entries.  (Otherwise, its XID appears
-	 * nowhere in permanent storage, so no one will ever care if it
-	 * committed.)  However, we must flush XLOG to disk if we made any XLOG
-	 * entries, whether in or out of transaction control.  For example, if we
-	 * reported a nextval() result to the client, this ensures that any XLOG
-	 * record generated by nextval will hit the disk before we report the
-	 * transaction committed.
+	 * If we made neither any XLOG entries nor any temp-rel updates,
+	 * we can omit recording the transaction commit at all.
 	 */
-	if (MyXactMadeXLogEntry)
+	if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate)
 	{
+		TransactionId xid = GetCurrentTransactionId();
 		XLogRecPtr	recptr;
 
+		/* Tell bufmgr and smgr to prepare for commit */
 		BufmgrCommit();
 
 		START_CRIT_SECTION();
 
+		/*
+		 * We only need to log the commit in xlog if the transaction made any
+		 * transaction-controlled XLOG entries.  (Otherwise, its XID appears
+		 * nowhere in permanent storage, so no one else will ever care if it
+		 * committed.)
+		 */
 		if (MyLastRecPtr.xrecoff != 0)
 		{
 			/* Need to emit a commit record */
@@ -567,30 +555,48 @@ RecordTransactionCommit(void)
 		}
 
 		/*
-		 * Sleep before flush! So we can flush more than one commit
-		 * records per single fsync.  (The idea is some other backend may
-		 * do the XLogFlush while we're sleeping.  This needs work still,
-		 * because on most Unixen, the minimum select() delay is 10msec or
-		 * more, which is way too long.)
-		 *
-		 * We do not sleep if enableFsync is not turned on, nor if there are
-		 * fewer than CommitSiblings other backends with active
-		 * transactions.
+		 * We must flush our XLOG entries to disk if we made any XLOG entries,
+		 * whether in or out of transaction control.  For example, if we
+		 * reported a nextval() result to the client, this ensures that any
+		 * XLOG record generated by nextval will hit the disk before we report
+		 * the transaction committed.
 		 */
-		if (CommitDelay > 0 && enableFsync &&
-			CountActiveBackends() >= CommitSiblings)
+		if (MyXactMadeXLogEntry)
 		{
-			struct timeval delay;
+			/*
+			 * Sleep before flush! So we can flush more than one commit
+			 * records per single fsync.  (The idea is some other backend may
+			 * do the XLogFlush while we're sleeping.  This needs work still,
+			 * because on most Unixen, the minimum select() delay is 10msec or
+			 * more, which is way too long.)
+			 *
+			 * We do not sleep if enableFsync is not turned on, nor if there
+			 * are fewer than CommitSiblings other backends with active
+			 * transactions.
+			 */
+			if (CommitDelay > 0 && enableFsync &&
+				CountActiveBackends() >= CommitSiblings)
+			{
+				struct timeval delay;
 
-			delay.tv_sec = 0;
-			delay.tv_usec = CommitDelay;
-			(void) select(0, NULL, NULL, NULL, &delay);
-		}
+				delay.tv_sec = 0;
+				delay.tv_usec = CommitDelay;
+				(void) select(0, NULL, NULL, NULL, &delay);
+			}
 
-		XLogFlush(recptr);
+			XLogFlush(recptr);
+		}
 
-		/* Mark the transaction committed in clog, if needed */
-		if (MyLastRecPtr.xrecoff != 0)
+		/*
+		 * We must mark the transaction committed in clog if its XID appears
+		 * either in permanent rels or in local temporary rels.  We test
+		 * this by seeing if we made transaction-controlled entries *OR*
+		 * local-rel tuple updates.  Note that if we made only the latter,
+		 * we have not emitted an XLOG record for our commit, and so in the
+		 * event of a crash the clog update might be lost.  This is okay
+		 * because no one else will ever care whether we committed.
+		 */
+		if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
 			TransactionIdCommit(xid);
 
 		END_CRIT_SECTION();
@@ -599,12 +605,10 @@ RecordTransactionCommit(void)
 	/* Break the chain of back-links in the XLOG records I output */
 	MyLastRecPtr.xrecoff = 0;
 	MyXactMadeXLogEntry = false;
+	MyXactMadeTempRelUpdate = false;
 
 	/* Show myself as out of the transaction in PGPROC array */
 	MyProc->logRec.xrecoff = 0;
-
-	if (leak)
-		ResetBufferPool(true);
 }
 
 
@@ -615,8 +619,10 @@ RecordTransactionCommit(void)
 static void
 AtCommit_Cache(void)
 {
-	/* Check for relcache reference-count leaks */
-	AtEOXactRelationCache(true);
+	/*
+	 * Clean up the relation cache.
+	 */
+	AtEOXact_RelationCache(true);
 	/*
 	 * Make catalog changes visible to all backends.
 	 */
@@ -679,45 +685,60 @@ AtCommit_Memory(void)
  * ----------------------------------------------------------------
  */
 
-/* --------------------------------
+/*
  *		RecordTransactionAbort
- * --------------------------------
  */
 static void
 RecordTransactionAbort(void)
 {
-	TransactionId xid = GetCurrentTransactionId();
-
 	/*
-	 * We only need to log the abort in xlog and clog if the transaction made
-	 * any transaction-controlled XLOG entries.  (Otherwise, its XID appears
-	 * nowhere in permanent storage, so no one will ever care if it
-	 * committed.)  We do not flush XLOG to disk in any case, since the
-	 * default assumption after a crash would be that we aborted, anyway.
-	 *
-	 * Extra check here is to catch case that we aborted partway through
-	 * RecordTransactionCommit ...
+	 * If we made neither any transaction-controlled XLOG entries nor any
+	 * temp-rel updates, we can omit recording the transaction abort at all.
+	 * No one will ever care that it aborted.
 	 */
-	if (MyLastRecPtr.xrecoff != 0 && !TransactionIdDidCommit(xid))
+	if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
 	{
-		XLogRecData rdata;
-		xl_xact_abort xlrec;
-		XLogRecPtr	recptr;
+		TransactionId xid = GetCurrentTransactionId();
 
-		xlrec.xtime = time(NULL);
-		rdata.buffer = InvalidBuffer;
-		rdata.data = (char *) (&xlrec);
-		rdata.len = SizeOfXactAbort;
-		rdata.next = NULL;
+		/*
+		 * Catch the scenario where we aborted partway through
+		 * RecordTransactionCommit ...
+		 */
+		if (TransactionIdDidCommit(xid))
+			elog(PANIC, "RecordTransactionAbort: xact %u already committed",
+				 xid);
 
 		START_CRIT_SECTION();
 
 		/*
-		 * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
+		 * We only need to log the abort in XLOG if the transaction made any
+		 * transaction-controlled XLOG entries.  (Otherwise, its XID appears
+		 * nowhere in permanent storage, so no one else will ever care if it
+		 * committed.)  We do not flush XLOG to disk in any case, since the
+		 * default assumption after a crash would be that we aborted, anyway.
 		 */
-		recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
+		if (MyLastRecPtr.xrecoff != 0)
+		{
+			XLogRecData rdata;
+			xl_xact_abort xlrec;
+			XLogRecPtr	recptr;
+
+			xlrec.xtime = time(NULL);
+			rdata.buffer = InvalidBuffer;
+			rdata.data = (char *) (&xlrec);
+			rdata.len = SizeOfXactAbort;
+			rdata.next = NULL;
+
+			/*
+			 * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
+			 */
+			recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
+		}
 
-		/* Mark the transaction aborted in clog */
+		/*
+		 * Mark the transaction aborted in clog.  This is not absolutely
+		 * necessary but we may as well do it while we are here.
+		 */
 		TransactionIdAbort(xid);
 
 		END_CRIT_SECTION();
@@ -726,14 +747,10 @@ RecordTransactionAbort(void)
 	/* Break the chain of back-links in the XLOG records I output */
 	MyLastRecPtr.xrecoff = 0;
 	MyXactMadeXLogEntry = false;
+	MyXactMadeTempRelUpdate = false;
 
 	/* Show myself as out of the transaction in PGPROC array */
 	MyProc->logRec.xrecoff = 0;
-
-	/*
-	 * Tell bufmgr and smgr to release resources.
-	 */
-	ResetBufferPool(false);		/* false -> is abort */
 }
 
 /* --------------------------------
@@ -743,7 +760,7 @@ RecordTransactionAbort(void)
 static void
 AtAbort_Cache(void)
 {
-	AtEOXactRelationCache(false);
+	AtEOXact_RelationCache(false);
 	AtEOXactInvalidationMessages(false);
 }
 
@@ -975,7 +992,6 @@ CommitTransaction(void)
 	 * noncritical resource releasing.
 	 */
 
-	RelationPurgeLocalRelation(true);
 	smgrDoPendingDeletes(true);
 
 	AtEOXact_GUC(true);
@@ -989,6 +1005,8 @@ CommitTransaction(void)
 	AtCommit_Locks();
 	AtEOXact_CatCache(true);
 	AtCommit_Memory();
+	AtEOXact_Buffers(true);
+	smgrabort();
 	AtEOXact_Files();
 
 	/* Count transaction commit in statistics collector */
@@ -1076,7 +1094,6 @@ AbortTransaction(void)
 		LWLockRelease(SInvalLock);
 	}
 
-	RelationPurgeLocalRelation(false);
 	smgrDoPendingDeletes(false);
 
 	AtEOXact_GUC(false);
@@ -1089,6 +1106,7 @@ AbortTransaction(void)
 	AtAbort_Cache();
 	AtEOXact_CatCache(false);
 	AtAbort_Memory();
+	AtEOXact_Buffers(false);
 	AtEOXact_Files();
 	AtAbort_Locks();
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 872722b856c7009f950dc95d69c0232238feac74..fbe61e5691c47a231bf35476c368ca8beb9437ce 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.100 2002/08/05 01:24:13 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.101 2002/08/06 02:36:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -136,11 +136,20 @@ bool		InRecovery = false;
  * to be set true.  The latter can be used to test whether the current xact
  * made any loggable changes (including out-of-xact changes, such as
  * sequence updates).
+ *
+ * When we insert/update/delete a tuple in a temporary relation, we do not
+ * make any XLOG record, since we don't care about recovering the state of
+ * the temp rel after a crash.  However, we will still need to remember
+ * whether our transaction committed or aborted in that case.  So, we must
+ * set MyXactMadeTempRelUpdate true to indicate that the XID will be of
+ * interest later.
  */
 XLogRecPtr	MyLastRecPtr = {0, 0};
 
 bool		MyXactMadeXLogEntry = false;
 
+bool		MyXactMadeTempRelUpdate = false;
+
 /*
  * ProcLastRecPtr points to the start of the last XLOG record inserted by the
  * current backend.  It is updated for all inserts, transaction-controlled
@@ -2923,6 +2932,7 @@ ShutdownXLOG(void)
 	/* suppress in-transaction check in CreateCheckPoint */
 	MyLastRecPtr.xrecoff = 0;
 	MyXactMadeXLogEntry = false;
+	MyXactMadeTempRelUpdate = false;
 
 	CritSectionCount++;
 	CreateDummyCaches();
@@ -3084,12 +3094,10 @@ CreateCheckPoint(bool shutdown)
 
 	/*
 	 * Having constructed the checkpoint record, ensure all shmem disk
-	 * buffers are flushed to disk.
+	 * buffers and commit-log buffers are flushed to disk.
 	 */
-	FlushBufferPool();
-
-	/* And commit-log buffers, too */
 	CheckPointCLOG();
+	FlushBufferPool();
 
 	/*
 	 * Now insert the checkpoint record into XLOG.
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index b61ad73212721e203786d1620540a810f1fab7b8..6bf905c6ea23e19304068d2ea6ccdd37acee6fee 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.218 2002/08/05 03:29:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.219 2002/08/06 02:36:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1919,7 +1919,7 @@ heap_truncate(Oid rid)
 	 * a rel created in the current xact (which would be deleted on abort,
 	 * anyway).
 	 */
-	if (IsTransactionBlock() && !rel->rd_myxactonly)
+	if (IsTransactionBlock() && !rel->rd_isnew)
 		elog(ERROR, "TRUNCATE TABLE cannot run inside a transaction block");
 
 	/*
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 7f558b4d9deeda50df687fa1ab1d24d1cfed8433..4206c33edb3cd5418562a98bcd2e6c78a7091b31 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.100 2002/08/05 03:29:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.101 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,7 +121,7 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 							  nullv,	/* info on nulls */
 							  &(heapTuple->t_self),		/* tid of heap tuple */
 							  heapRelation,
-							  relationDescs[i]->rd_uniqueindex);
+							  relationDescs[i]->rd_index->indisunique);
 
 		if (result)
 			pfree(result);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index f8a05b619de484897ddb9e88cec4e34b8ef0627d..a33fcd24a40f02769fabb11ce6e7107f92156850 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.83 2002/07/16 22:12:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.84 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -237,6 +237,7 @@ DefineSequence(CreateSeqStmt *seq)
 	 * means two log records instead of one :-(
 	 */
 	LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
+
 	START_CRIT_SECTION();
 
 	{
@@ -260,6 +261,8 @@ DefineSequence(CreateSeqStmt *seq)
 		tuple->t_data->t_infomask |= HEAP_XMIN_COMMITTED;
 	}
 
+	/* XLOG stuff */
+	if (!rel->rd_istemp)
 	{
 		xl_seq_rec	xlrec;
 		XLogRecPtr	recptr;
@@ -287,6 +290,7 @@ DefineSequence(CreateSeqStmt *seq)
 		PageSetLSN(page, recptr);
 		PageSetSUI(page, ThisStartUpID);
 	}
+
 	END_CRIT_SECTION();
 
 	LockBuffer(buf, BUFFER_LOCK_UNLOCK);
@@ -437,7 +441,9 @@ nextval(PG_FUNCTION_ARGS)
 	elm->cached = last;			/* last fetched number */
 
 	START_CRIT_SECTION();
-	if (logit)
+
+	/* XLOG stuff */
+	if (logit && !seqrel->rd_istemp)
 	{
 		xl_seq_rec	xlrec;
 		XLogRecPtr	recptr;
@@ -449,9 +455,11 @@ nextval(PG_FUNCTION_ARGS)
 		rdata[0].len = sizeof(xl_seq_rec);
 		rdata[0].next = &(rdata[1]);
 
+		/* set values that will be saved in xlog */
 		seq->last_value = next;
 		seq->is_called = true;
 		seq->log_cnt = 0;
+
 		rdata[1].buffer = InvalidBuffer;
 		rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;
 		rdata[1].len = ((PageHeader) page)->pd_special -
@@ -468,6 +476,7 @@ nextval(PG_FUNCTION_ARGS)
 	seq->last_value = last;		/* last fetched number */
 	seq->is_called = true;
 	seq->log_cnt = log;			/* how much is logged */
+
 	END_CRIT_SECTION();
 
 	LockBuffer(buf, BUFFER_LOCK_UNLOCK);
@@ -550,6 +559,9 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
 								 * values) */
 
 	START_CRIT_SECTION();
+
+	/* XLOG stuff */
+	if (!seqrel->rd_istemp)
 	{
 		xl_seq_rec	xlrec;
 		XLogRecPtr	recptr;
@@ -562,9 +574,11 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
 		rdata[0].len = sizeof(xl_seq_rec);
 		rdata[0].next = &(rdata[1]);
 
+		/* set values that will be saved in xlog */
 		seq->last_value = next;
 		seq->is_called = true;
 		seq->log_cnt = 0;
+
 		rdata[1].buffer = InvalidBuffer;
 		rdata[1].data = (char *) page + ((PageHeader) page)->pd_upper;
 		rdata[1].len = ((PageHeader) page)->pd_special -
@@ -576,10 +590,12 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
 		PageSetLSN(page, recptr);
 		PageSetSUI(page, ThisStartUpID);
 	}
+
 	/* save info in sequence relation */
 	seq->last_value = next;		/* last fetched number */
 	seq->is_called = iscalled;
 	seq->log_cnt = (iscalled) ? 0 : 1;
+
 	END_CRIT_SECTION();
 
 	LockBuffer(buf, BUFFER_LOCK_UNLOCK);
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index c893ea86a09faef3d2fa15ddd048d3a74708c495..8d2cd4da58c1d1ef7f56a4c0c3917123694f4114 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.232 2002/07/20 05:16:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.233 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1899,6 +1899,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 					newtup.t_data = (HeapTupleHeader) PageGetItem(ToPage, newitemid);
 					ItemPointerSet(&(newtup.t_self), destvacpage->blkno, newoff);
 
+					/* XLOG stuff */
+					if (!onerel->rd_istemp)
 					{
 						XLogRecPtr	recptr =
 						log_heap_move(onerel, Cbuf, tuple.t_self,
@@ -1912,6 +1914,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 						PageSetLSN(ToPage, recptr);
 						PageSetSUI(ToPage, ThisStartUpID);
 					}
+					else
+					{
+						/* No XLOG record, but still need to flag that XID exists on disk */
+						MyXactMadeTempRelUpdate = true;
+					}
+
 					END_CRIT_SECTION();
 
 					if (destvacpage->blkno > last_move_dest_block)
@@ -2042,6 +2050,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 			tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
 			HeapTupleHeaderSetXvac(tuple.t_data, myXID);
 
+			/* XLOG stuff */
+			if (!onerel->rd_istemp)
 			{
 				XLogRecPtr	recptr =
 				log_heap_move(onerel, buf, tuple.t_self,
@@ -2052,6 +2062,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 				PageSetLSN(ToPage, recptr);
 				PageSetSUI(ToPage, ThisStartUpID);
 			}
+			else
+			{
+				/* No XLOG record, but still need to flag that XID exists on disk */
+				MyXactMadeTempRelUpdate = true;
+			}
+
 			END_CRIT_SECTION();
 
 			cur_page->offsets_used++;
@@ -2321,8 +2337,13 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 
 			}
 			Assert(vacpage->offsets_free == num_tuples);
+
 			START_CRIT_SECTION();
+
 			uncnt = PageRepairFragmentation(page, unused);
+
+			/* XLOG stuff */
+			if (!onerel->rd_istemp)
 			{
 				XLogRecPtr	recptr;
 
@@ -2331,7 +2352,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
 				PageSetLSN(page, recptr);
 				PageSetSUI(page, ThisStartUpID);
 			}
+			else
+			{
+				/* No XLOG record, but still need to flag that XID exists on disk */
+				MyXactMadeTempRelUpdate = true;
+			}
+
 			END_CRIT_SECTION();
+
 			LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 			WriteBuffer(buf);
 		}
@@ -2450,12 +2478,17 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
 	Assert(vacpage->offsets_used == 0);
 
 	START_CRIT_SECTION();
+
 	for (i = 0; i < vacpage->offsets_free; i++)
 	{
 		itemid = PageGetItemId(page, vacpage->offsets[i]);
 		itemid->lp_flags &= ~LP_USED;
 	}
+
 	uncnt = PageRepairFragmentation(page, unused);
+
+	/* XLOG stuff */
+	if (!onerel->rd_istemp)
 	{
 		XLogRecPtr	recptr;
 
@@ -2464,6 +2497,12 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
 		PageSetLSN(page, recptr);
 		PageSetSUI(page, ThisStartUpID);
 	}
+	else
+	{
+		/* No XLOG record, but still need to flag that XID exists on disk */
+		MyXactMadeTempRelUpdate = true;
+	}
+
 	END_CRIT_SECTION();
 }
 
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index bbf9e39ae80496038633a64b44af52d58358c58b..4fb613cc67e522844e30380fd854f844198f1971 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.17 2002/07/20 05:16:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.18 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -523,6 +523,8 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 
 	uncnt = PageRepairFragmentation(page, unused);
 
+	/* XLOG stuff */
+	if (!onerel->rd_istemp)
 	{
 		XLogRecPtr	recptr;
 
@@ -531,6 +533,12 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
 		PageSetLSN(page, recptr);
 		PageSetSUI(page, ThisStartUpID);
 	}
+	else
+	{
+		/* No XLOG record, but still need to flag that XID exists on disk */
+		MyXactMadeTempRelUpdate = true;
+	}
+
 	END_CRIT_SECTION();
 
 	return tupindex;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index c2bd2de48abe47931c1d062f1d18f7fe23414d84..24f232469b0ac281ca05986ecb86a1d4a59f3518 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.87 2002/07/20 05:16:58 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.88 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -691,7 +691,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
 							  nullv,	/* info on nulls */
 							  &(heapTuple->t_self),		/* tid of heap tuple */
 							  heapRelation,
-							  relationDescs[i]->rd_uniqueindex && !is_vacuum);
+							  relationDescs[i]->rd_index->indisunique && !is_vacuum);
 
 		/*
 		 * keep track of index inserts for debugging
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 6132b732f864f9376a0cfc05d2c7e04f7b08c7aa..a8c56562f2d6074299a98f64830562b2e73b84a3 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.49 2002/06/20 20:29:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.50 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -258,7 +258,7 @@ ShutdownBufferPoolAccess(void)
 	/* Release any buffer context locks we are holding */
 	UnlockBuffers();
 	/* Release any buffer reference counts we are holding */
-	ResetBufferPool(false);
+	AtEOXact_Buffers(false);
 }
 
 /* -----------------------------------------------------
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index b2c19e99f47b48ac439a9d5c73810a0ddc8a4793..1ca7af3b775774b6dfdecc083dcab982bbe8396e 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.127 2002/07/02 05:47:37 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.128 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,16 +57,9 @@
 #include "pgstat.h"
 
 #define BufferGetLSN(bufHdr)	\
-	(*((XLogRecPtr*)MAKE_PTR((bufHdr)->data)))
+	(*((XLogRecPtr*) MAKE_PTR((bufHdr)->data)))
 
 
-extern long int ReadBufferCount;
-extern long int ReadLocalBufferCount;
-extern long int BufferHitCount;
-extern long int LocalBufferHitCount;
-extern long int BufferFlushCount;
-extern long int LocalBufferFlushCount;
-
 static void WaitIO(BufferDesc *buf);
 static void StartBufferIO(BufferDesc *buf, bool forInput);
 static void TerminateBufferIO(BufferDesc *buf);
@@ -82,16 +75,12 @@ static Buffer ReadBufferInternal(Relation reln, BlockNumber blockNum,
 				   bool bufferLockHeld);
 static BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum,
 			bool *foundPtr);
-static int	ReleaseBufferWithBufferLock(Buffer buffer);
 static int	BufferReplace(BufferDesc *bufHdr);
 #ifdef NOT_USED
 void		PrintBufferDescs(void);
 #endif
 
 static void write_buffer(Buffer buffer, bool unpin);
-static void drop_relfilenode_buffers(RelFileNode rnode,
-                                     bool do_local, bool do_both);
-static int release_buffer(Buffer buffer, bool havelock);
 
 /*
  * ReadBuffer -- returns a buffer containing the requested
@@ -140,7 +129,7 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
 	bool		isLocalBuf;
 
 	isExtend = (blockNum == P_NEW);
-	isLocalBuf = reln->rd_myxactonly;
+	isLocalBuf = reln->rd_istemp;
 
 	if (isLocalBuf)
 	{
@@ -684,10 +673,10 @@ ReleaseAndReadBuffer(Buffer buffer,
 /*
  * BufferSync -- Write all dirty buffers in the pool.
  *
- * This is called at checkpoint time and write out all dirty buffers.
+ * This is called at checkpoint time and writes out all dirty shared buffers.
  */
 void
-BufferSync()
+BufferSync(void)
 {
 	int			i;
 	BufferDesc *bufHdr;
@@ -780,8 +769,7 @@ BufferSync()
 			status = smgrblindwrt(DEFAULT_SMGR,
 								  bufHdr->tag.rnode,
 								  bufHdr->tag.blockNum,
-								  (char *) MAKE_PTR(bufHdr->data),
-								  true);		/* must fsync */
+								  (char *) MAKE_PTR(bufHdr->data));
 		}
 		else
 		{
@@ -908,19 +896,16 @@ ResetBufferUsage(void)
 	NDirectFileWrite = 0;
 }
 
-/* ----------------------------------------------
- *		ResetBufferPool
- *
- *		This routine is supposed to be called when a transaction aborts.
- *		It will release all the buffer pins held by the transaction.
- *		Currently, we also call it during commit if BufferPoolCheckLeak
- *		detected a problem --- in that case, isCommit is TRUE, and we
- *		only clean up buffer pin counts.
+/*
+ *		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 elog 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.
  */
 void
-ResetBufferPool(bool isCommit)
+AtEOXact_Buffers(bool isCommit)
 {
 	int			i;
 
@@ -928,7 +913,16 @@ ResetBufferPool(bool isCommit)
 	{
 		if (PrivateRefCount[i] != 0)
 		{
-			BufferDesc *buf = &BufferDescriptors[i];
+			BufferDesc *buf = &(BufferDescriptors[i]);
+
+			if (isCommit)
+				elog(WARNING,
+					 "Buffer Leak: [%03d] (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,
+					 buf->refcount, PrivateRefCount[i]);
 
 			PrivateRefCount[i] = 1;		/* make sure we release shared pin */
 			LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
@@ -938,48 +932,15 @@ ResetBufferPool(bool isCommit)
 		}
 	}
 
-	ResetLocalBufferPool();
-
-	if (!isCommit)
-		smgrabort();
+	AtEOXact_LocalBuffers(isCommit);
 }
 
 /*
- * BufferPoolCheckLeak
- *
- *		check if there is buffer leak
- */
-bool
-BufferPoolCheckLeak(void)
-{
-	int			i;
-	bool		result = false;
-
-	for (i = 0; i < NBuffers; i++)
-	{
-		if (PrivateRefCount[i] != 0)
-		{
-			BufferDesc *buf = &(BufferDescriptors[i]);
-
-			elog(WARNING,
-				 "Buffer Leak: [%03d] (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,
-				 buf->refcount, PrivateRefCount[i]);
-			result = true;
-		}
-	}
-	return result;
-}
-
-/* ------------------------------------------------
  * FlushBufferPool
  *
- * Flush all dirty blocks in buffer pool to disk
- * at the checkpoint time
- * ------------------------------------------------
+ * Flush all dirty blocks in buffer pool to disk at the checkpoint time.
+ * Local relations do not participate in checkpoints, so they don't need to be
+ * flushed.
  */
 void
 FlushBufferPool(void)
@@ -989,16 +950,13 @@ FlushBufferPool(void)
 }
 
 /*
- * At the commit time we have to flush local buffer pool only
+ * Do whatever is needed to prepare for commit at the bufmgr and smgr levels
  */
 void
 BufmgrCommit(void)
 {
-	LocalBufferSync();
+	/* Nothing to do in bufmgr anymore... */
 
-	/*
-	 * All files created in current transaction will be fsync-ed
-	 */
 	smgrcommit();
 }
 
@@ -1051,15 +1009,15 @@ BufferReplace(BufferDesc *bufHdr)
 
 	if (reln != (Relation) NULL)
 	{
-		status = smgrwrite(DEFAULT_SMGR, reln, bufHdr->tag.blockNum,
+		status = smgrwrite(DEFAULT_SMGR, reln,
+						   bufHdr->tag.blockNum,
 						   (char *) MAKE_PTR(bufHdr->data));
 	}
 	else
 	{
 		status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode,
 							  bufHdr->tag.blockNum,
-							  (char *) MAKE_PTR(bufHdr->data),
-							  false);	/* no fsync */
+							  (char *) MAKE_PTR(bufHdr->data));
 	}
 
 	/* drop relcache refcnt incremented by RelationNodeCacheGetRelation */
@@ -1091,31 +1049,55 @@ RelationGetNumberOfBlocks(Relation relation)
 {
 	/*
 	 * relation->rd_nblocks should be accurate already if the relation is
-	 * myxactonly.	(XXX how safe is that really?)	Don't call smgr on a
-	 * view, either.
+	 * new or temp, because no one else should be modifying it.  Otherwise
+	 * we need to ask the smgr for the current physical file length.
+	 *
+	 * Don't call smgr on a view, either.
 	 */
 	if (relation->rd_rel->relkind == RELKIND_VIEW)
 		relation->rd_nblocks = 0;
-	else if (!relation->rd_myxactonly)
+	else if (!relation->rd_isnew && !relation->rd_istemp)
 		relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
 	return relation->rd_nblocks;
 }
 
-/*
- * drop_relfilenode_buffers -- common functionality for
- *                             DropRelationBuffers and
- *                             DropRelFileNodeBuffers
+/* ---------------------------------------------------------------------
+ *		DropRelationBuffers
  *
- *		XXX currently it sequentially searches the buffer pool, should be
- *		changed to more clever ways of searching.
+ *		This function removes all the buffered pages for a relation
+ *		from the buffer pool.  Dirty pages are simply dropped, without
+ *		bothering to write them out first.	This is NOT rollback-able,
+ *		and so should be used only with extreme caution!
+ *
+ *		We assume that the caller holds an exclusive lock on the relation,
+ *		which should assure that no new buffers will be acquired for the rel
+ *		meanwhile.
+ * --------------------------------------------------------------------
  */
-static void
-drop_relfilenode_buffers(RelFileNode rnode, bool do_local, bool do_both)
+void
+DropRelationBuffers(Relation rel)
+{
+	DropRelFileNodeBuffers(rel->rd_node, rel->rd_istemp);
+}
+
+/* ---------------------------------------------------------------------
+ *		DropRelFileNodeBuffers
+ *
+ *		This is the same as DropRelationBuffers, except that the target
+ *		relation is specified by RelFileNode and temp status.
+ *
+ *		This is NOT rollback-able.	One legitimate use is to clear the
+ *		buffer cache of buffers for a relation that is being deleted
+ *		during transaction abort.
+ * --------------------------------------------------------------------
+ */
+void
+DropRelFileNodeBuffers(RelFileNode rnode, bool istemp)
 {
 	int			i;
 	BufferDesc *bufHdr;
 
-	if (do_local)
+	if (istemp)
 	{
 		for (i = 0; i < NLocBuffer; i++)
 		{
@@ -1128,8 +1110,7 @@ drop_relfilenode_buffers(RelFileNode rnode, bool do_local, bool do_both)
 				bufHdr->tag.rnode.relNode = InvalidOid;
 			}
 		}
-		if (!do_both)
-			return;
+		return;
 	}
 
 	LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
@@ -1160,18 +1141,19 @@ recheck:
 			bufHdr->cntxDirty = false;
 
 			/*
-			 * Release any refcount we may have.
-			 *
-			 * This is very probably dead code, and if it isn't then it's
-			 * probably wrong.	I added the Assert to find out --- tgl
-			 * 11/99.
+			 * Release any refcount we may have.  If someone else has a
+			 * pin on the buffer, we got trouble.
 			 */
 			if (!(bufHdr->flags & BM_FREE))
 			{
-				/* Assert checks that buffer will actually get freed! */
-				Assert(PrivateRefCount[i - 1] == 1 &&
-					   bufHdr->refcount == 1);
-				ReleaseBufferWithBufferLock(i);
+				/* the sole pin should be ours */
+				if (bufHdr->refcount != 1 || PrivateRefCount[i - 1] == 0)
+					elog(FATAL, "DropRelFileNodeBuffers: block %u is referenced (private %ld, global %d)",
+						 bufHdr->tag.blockNum,
+						 PrivateRefCount[i - 1], bufHdr->refcount);
+				/* Make sure it will be released */
+				PrivateRefCount[i - 1] = 1;
+				UnpinBuffer(bufHdr);
 			}
 
 			/*
@@ -1184,43 +1166,6 @@ recheck:
 	LWLockRelease(BufMgrLock);
 }
 
-/* ---------------------------------------------------------------------
- *		DropRelationBuffers
- *
- *		This function removes all the buffered pages for a relation
- *		from the buffer pool.  Dirty pages are simply dropped, without
- *		bothering to write them out first.	This is NOT rollback-able,
- *		and so should be used only with extreme caution!
- *
- *		We assume that the caller holds an exclusive lock on the relation,
- *		which should assure that no new buffers will be acquired for the rel
- *		meanwhile.
- * --------------------------------------------------------------------
- */
-void
-DropRelationBuffers(Relation rel)
-{
-	drop_relfilenode_buffers(rel->rd_node, rel->rd_myxactonly, false);
-}
-
-/* ---------------------------------------------------------------------
- *		DropRelFileNodeBuffers
- *
- *		This is the same as DropRelationBuffers, except that the target
- *		relation is specified by RelFileNode.
- *
- *		This is NOT rollback-able.	One legitimate use is to clear the
- *		buffer cache of buffers for a relation that is being deleted
- *		during transaction abort.
- * --------------------------------------------------------------------
- */
-void
-DropRelFileNodeBuffers(RelFileNode rnode)
-{
-	/* We have to search both local and shared buffers... */
-	drop_relfilenode_buffers(rnode, true, true);
-}
-
 /* ---------------------------------------------------------------------
  *		DropBuffers
  *
@@ -1296,7 +1241,7 @@ recheck:
  */
 #ifdef NOT_USED
 void
-PrintBufferDescs()
+PrintBufferDescs(void)
 {
 	int			i;
 	BufferDesc *buf = BufferDescriptors;
@@ -1331,7 +1276,7 @@ blockNum=%u, flags=0x%x, refcount=%d %ld)",
 
 #ifdef NOT_USED
 void
-PrintPinnedBufs()
+PrintPinnedBufs(void)
 {
 	int			i;
 	BufferDesc *buf = BufferDescriptors;
@@ -1351,33 +1296,6 @@ blockNum=%u, flags=0x%x, refcount=%d %ld)",
 }
 #endif
 
-/*
- * BufferPoolBlowaway
- *
- * this routine is solely for the purpose of experiments -- sometimes
- * you may want to blowaway whatever is left from the past in buffer
- * pool and start measuring some performance with a clean empty buffer
- * pool.
- */
-#ifdef NOT_USED
-void
-BufferPoolBlowaway()
-{
-	int			i;
-
-	BufferSync();
-	for (i = 1; i <= NBuffers; i++)
-	{
-		if (BufferIsValid(i))
-		{
-			while (BufferIsValid(i))
-				ReleaseBuffer(i);
-		}
-		BufTableDelete(&BufferDescriptors[i - 1]);
-	}
-}
-#endif
-
 /* ---------------------------------------------------------------------
  *		FlushRelationBuffers
  *
@@ -1428,7 +1346,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 	XLogRecPtr	recptr;
 	int			status;
 
-	if (rel->rd_myxactonly)
+	if (rel->rd_istemp)
 	{
 		for (i = 0; i < NLocBuffer; i++)
 		{
@@ -1544,12 +1462,14 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 	return 0;
 }
 
+#undef ReleaseBuffer
+
 /*
- * release_buffer -- common functionality for
- *                   ReleaseBuffer and ReleaseBufferWithBufferLock
+ * ReleaseBuffer -- remove the pin on a buffer without
+ *		marking it dirty.
  */
-static int
-release_buffer(Buffer buffer, bool havelock)
+int
+ReleaseBuffer(Buffer buffer)
 {
 	BufferDesc *bufHdr;
 
@@ -1570,41 +1490,14 @@ release_buffer(Buffer buffer, bool havelock)
 		PrivateRefCount[buffer - 1]--;
 	else
 	{
-		if (!havelock)
-			LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
-
+		LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 		UnpinBuffer(bufHdr);
-
-		if (!havelock)
-			LWLockRelease(BufMgrLock);
+		LWLockRelease(BufMgrLock);
 	}
 
 	return STATUS_OK;
 }
 
-#undef ReleaseBuffer
-
-/*
- * ReleaseBuffer -- remove the pin on a buffer without
- *		marking it dirty.
- */
-int
-ReleaseBuffer(Buffer buffer)
-{
-	return release_buffer(buffer, false);
-}
-
-/*
- * ReleaseBufferWithBufferLock
- *		Same as ReleaseBuffer except we hold the bufmgr lock
- */
-static int
-ReleaseBufferWithBufferLock(Buffer buffer)
-{
-	return release_buffer(buffer, true);
-}
-
-
 #ifdef NOT_USED
 void
 IncrBufferRefCount_Debug(char *file, int line, Buffer buffer)
@@ -1847,10 +1740,13 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
 	BufferDesc *bufHdr;
 
 	if (BufferIsLocal(buffer))
+	{
+		WriteLocalBuffer(buffer, false);
 		return;
+	}
 
 	if (BAD_BUFFER_ID(buffer))
-		return;
+		elog(ERROR, "SetBufferCommitInfoNeedsSave: bad buffer %d", buffer);
 
 	bufHdr = &BufferDescriptors[buffer - 1];
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index d5edc570b6ec07f3eeb1cd224861898d7280bf53..50168c8b306b7eb9baca79b9cf4a4d91d38c5ab2 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -1,48 +1,37 @@
 /*-------------------------------------------------------------------------
  *
  * localbuf.c
- *	  local buffer manager. Fast buffer manager for temporary tables
- *	  or special cases when the operation is not visible to other backends.
- *
- *	  When a relation is being created, the descriptor will have rd_islocal
- *	  set to indicate that the local buffer manager should be used. During
- *	  the same transaction the relation is being created, any inserts or
- *	  selects from the newly created relation will use the local buffer
- *	  pool. rd_islocal is reset at the end of a transaction (commit/abort).
- *	  This is useful for queries like SELECT INTO TABLE and create index.
+ *	  local buffer manager. Fast buffer manager for temporary tables,
+ *	  which never need to be WAL-logged or checkpointed, etc.
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.44 2002/06/20 20:29:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.45 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
-#include <sys/types.h>
-#include <sys/file.h>
-#include <math.h>
-#include <signal.h>
-
-#include "executor/execdebug.h"
 #include "storage/buf_internals.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
 #include "utils/relcache.h"
 
-extern long int LocalBufferFlushCount;
 
+/*#define LBDEBUG*/
+
+/* should be a GUC parameter some day */
 int			NLocBuffer = 64;
+
 BufferDesc *LocalBufferDescriptors = NULL;
 Block	   *LocalBufferBlockPointers = NULL;
 long	   *LocalRefCount = NULL;
 
 static int	nextFreeLocalBuf = 0;
 
-/*#define LBDEBUG*/
 
 /*
  * LocalBufferAlloc -
@@ -61,11 +50,11 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 			reln->rd_node.relNode &&
 			LocalBufferDescriptors[i].tag.blockNum == blockNum)
 		{
-
 #ifdef LBDEBUG
 			fprintf(stderr, "LB ALLOC (%u,%d) %d\n",
 					RelationGetRelid(reln), blockNum, -i - 1);
 #endif
+
 			LocalRefCount[i]++;
 			*foundPtr = TRUE;
 			return &LocalBufferDescriptors[i];
@@ -94,14 +83,17 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 		elog(ERROR, "no empty local buffer.");
 
 	/*
-	 * this buffer is not referenced but it might still be dirty (the last
-	 * transaction to touch it doesn't need its contents but has not
-	 * flushed it).  if that's the case, write it out before reusing it!
+	 * this buffer is not referenced but it might still be dirty.
+	 * if that's the case, write it out before reusing it!
 	 */
 	if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
 	{
 		Relation	bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
+		/*
+		 * The relcache is not supposed to throw away temp rels, so this
+		 * should always succeed.
+		 */
 		Assert(bufrel != NULL);
 
 		/* flush this page */
@@ -113,26 +105,19 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 		RelationDecrementReferenceCount(bufrel);
 	}
 
-	/*
-	 * it's all ours now.
-	 *
-	 * We need not in tblNode currently but will in future I think, when
-	 * we'll give up rel->rd_fd to fmgr cache.
-	 */
-	bufHdr->tag.rnode = reln->rd_node;
-	bufHdr->tag.blockNum = blockNum;
-	bufHdr->flags &= ~BM_DIRTY;
-	bufHdr->cntxDirty = false;
-
 	/*
 	 * lazy memory allocation: allocate space on first use of a buffer.
+	 *
+	 * Note this path cannot be taken for a buffer that was previously
+	 * in use, so it's okay to do it (and possibly error out) before
+	 * marking the buffer as valid.
 	 */
 	if (bufHdr->data == (SHMEM_OFFSET) 0)
 	{
 		char	   *data = (char *) malloc(BLCKSZ);
 
 		if (data == NULL)
-			elog(FATAL, "Out of memory in LocalBufferAlloc");
+			elog(ERROR, "Out of memory in LocalBufferAlloc");
 
 		/*
 		 * This is a bit of a hack: bufHdr->data needs to be a shmem
@@ -147,13 +132,24 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 		LocalBufferBlockPointers[-(bufHdr->buf_id + 2)] = (Block) data;
 	}
 
+	/*
+	 * it's all ours now.
+	 *
+	 * We need not in tblNode currently but will in future I think, when
+	 * we'll give up rel->rd_fd to fmgr cache.
+	 */
+	bufHdr->tag.rnode = reln->rd_node;
+	bufHdr->tag.blockNum = blockNum;
+	bufHdr->flags &= ~BM_DIRTY;
+	bufHdr->cntxDirty = false;
+
 	*foundPtr = FALSE;
 	return bufHdr;
 }
 
 /*
  * WriteLocalBuffer -
- *	  writes out a local buffer
+ *	  writes out a local buffer (actually, just marks it dirty)
  */
 void
 WriteLocalBuffer(Buffer buffer, bool release)
@@ -180,7 +176,7 @@ WriteLocalBuffer(Buffer buffer, bool release)
  * InitLocalBuffer -
  *	  init the local buffer cache. Since most queries (esp. multi-user ones)
  *	  don't involve local buffers, we delay allocating actual memory for the
- *	  buffer until we need it.
+ *	  buffers until we need them; just make the buffer headers here.
  */
 void
 InitLocalBuffer(void)
@@ -211,65 +207,30 @@ InitLocalBuffer(void)
 }
 
 /*
- * LocalBufferSync
- *
- * Flush all dirty buffers in the local buffer cache at commit time.
- * Since the buffer cache is only used for keeping relations visible
- * during a transaction, we will not need these buffers again.
+ * AtEOXact_LocalBuffers - clean up at end of transaction.
  *
- * Note that we have to *flush* local buffers because of them are not
- * visible to checkpoint makers. But we can skip XLOG flush check.
+ * This is just like AtEOXact_Buffers, but for local buffers.
  */
 void
-LocalBufferSync(void)
+AtEOXact_LocalBuffers(bool isCommit)
 {
 	int			i;
 
 	for (i = 0; i < NLocBuffer; i++)
 	{
-		BufferDesc *buf = &LocalBufferDescriptors[i];
-		Relation	bufrel;
-
-		if (buf->flags & BM_DIRTY || buf->cntxDirty)
+		if (LocalRefCount[i] != 0)
 		{
-#ifdef LBDEBUG
-			fprintf(stderr, "LB SYNC %d\n", -i - 1);
-#endif
-			bufrel = RelationNodeCacheGetRelation(buf->tag.rnode);
-
-			Assert(bufrel != NULL);
+			BufferDesc *buf = &(LocalBufferDescriptors[i]);
 
-			smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum,
-					  (char *) MAKE_PTR(buf->data));
-			smgrmarkdirty(DEFAULT_SMGR, bufrel, buf->tag.blockNum);
-			LocalBufferFlushCount++;
+			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,
+					 buf->refcount, LocalRefCount[i]);
 
-			/* drop relcache refcount from RelationNodeCacheGetRelation */
-			RelationDecrementReferenceCount(bufrel);
-
-			buf->flags &= ~BM_DIRTY;
-			buf->cntxDirty = false;
+			LocalRefCount[i] = 0;
 		}
 	}
-
-	MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer);
-	nextFreeLocalBuf = 0;
-}
-
-void
-ResetLocalBufferPool(void)
-{
-	int			i;
-
-	for (i = 0; i < NLocBuffer; i++)
-	{
-		BufferDesc *buf = &LocalBufferDescriptors[i];
-
-		buf->tag.rnode.relNode = InvalidOid;
-		buf->flags &= ~BM_DIRTY;
-		buf->cntxDirty = false;
-	}
-
-	MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer);
-	nextFreeLocalBuf = 0;
 }
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 391a078e602ea168a8d0cecd78d2f35e41eb6bf7..8be2ed219b99b6343e54f159c8681b103db26daa 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.92 2002/06/20 20:29:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.93 2002/08/06 02:36:34 tgl Exp $
  *
  * NOTES:
  *
@@ -119,8 +119,7 @@ typedef struct vfd
 	unsigned short fdstate;		/* bitflags for VFD's state */
 
 /* these are the assigned bits in fdstate: */
-#define FD_DIRTY		(1 << 0)	/* written to, but not yet fsync'd */
-#define FD_TEMPORARY	(1 << 1)	/* should be unlinked when closed */
+#define FD_TEMPORARY	(1 << 0)	/* should be unlinked when closed */
 
 	File		nextFree;		/* link to next free VFD, if in freelist */
 	File		lruMoreRecently;	/* doubly linked recency-of-use list */
@@ -396,15 +395,6 @@ LruDelete(File file)
 	vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
 	Assert(vfdP->seekPos != -1L);
 
-	/* if we have written to the file, sync it before closing */
-	if (vfdP->fdstate & FD_DIRTY)
-	{
-		if (pg_fsync(vfdP->fd))
-			elog(LOG, "LruDelete: failed to fsync %s: %m",
-				 vfdP->fileName);
-		vfdP->fdstate &= ~FD_DIRTY;
-	}
-
 	/* close the file */
 	if (close(vfdP->fd))
 		elog(LOG, "LruDelete: failed to close %s: %m",
@@ -725,17 +715,8 @@ fileNameOpenFile(FileName fileName,
 	/* Saved flags are adjusted to be OK for re-opening file */
 	vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
 	vfdP->fileMode = fileMode;
-
 	vfdP->seekPos = 0;
-
-	/*
-	 * Have to fsync file on commit. Alternative way - log file creation
-	 * and fsync log before actual file creation.
-	 */
-	if (fileFlags & O_CREAT)
-		vfdP->fdstate = FD_DIRTY;
-	else
-		vfdP->fdstate = 0x0;
+	vfdP->fdstate = 0x0;
 
 	return file;
 }
@@ -841,15 +822,6 @@ FileClose(File file)
 		/* remove the file from the lru ring */
 		Delete(file);
 
-		/* if we did any writes, sync the file before closing */
-		if (vfdP->fdstate & FD_DIRTY)
-		{
-			if (pg_fsync(vfdP->fd))
-				elog(LOG, "FileClose: failed to fsync %s: %m",
-					 vfdP->fileName);
-			vfdP->fdstate &= ~FD_DIRTY;
-		}
-
 		/* close the file */
 		if (close(vfdP->fd))
 			elog(LOG, "FileClose: failed to close %s: %m",
@@ -1022,108 +994,11 @@ FileTruncate(File file, long offset)
 	DO_DB(elog(LOG, "FileTruncate %d (%s)",
 			   file, VfdCache[file].fileName));
 
-	FileSync(file);
 	FileAccess(file);
 	returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
 	return returnCode;
 }
 
-/*
- * FileSync --- if a file is marked as dirty, fsync it.
- *
- * The FD_DIRTY bit is slightly misnamed: it doesn't mean that we need to
- * write the file, but that we *have* written it and need to execute an
- * fsync() to ensure the changes are down on disk before we mark the current
- * transaction committed.
- *
- * FD_DIRTY is set by FileWrite or by an explicit FileMarkDirty() call.
- * It is cleared after successfully fsync'ing the file.  FileClose() will
- * fsync a dirty File that is about to be closed, since there will be no
- * other place to remember the need to fsync after the VFD is gone.
- *
- * Note that the DIRTY bit is logically associated with the actual disk file,
- * not with any particular kernel FD we might have open for it.  We assume
- * that fsync will force out any dirty buffers for that file, whether or not
- * they were written through the FD being used for the fsync call --- they
- * might even have been written by some other backend!
- *
- * Note also that LruDelete currently fsyncs a dirty file that it is about
- * to close the kernel file descriptor for.  The idea there is to avoid
- * having to re-open the kernel descriptor later.  But it's not real clear
- * that this is a performance win; we could end up fsyncing the same file
- * multiple times in a transaction, which would probably cost more time
- * than is saved by avoiding an open() call.  This should be studied.
- *
- * This routine used to think it could skip the fsync if the file is
- * physically closed, but that is now WRONG; see comments for FileMarkDirty.
- */
-int
-FileSync(File file)
-{
-	int			returnCode;
-
-	Assert(FileIsValid(file));
-
-	if (!(VfdCache[file].fdstate & FD_DIRTY))
-	{
-		/* Need not sync if file is not dirty. */
-		returnCode = 0;
-	}
-	else if (!enableFsync)
-	{
-		/* Don't force the file open if pg_fsync isn't gonna sync it. */
-		returnCode = 0;
-		VfdCache[file].fdstate &= ~FD_DIRTY;
-	}
-	else
-	{
-		/*
-		 * We don't use FileAccess() because we don't want to force the
-		 * file to the front of the LRU ring; we aren't expecting to
-		 * access it again soon.
-		 */
-		if (FileIsNotOpen(file))
-		{
-			returnCode = LruInsert(file);
-			if (returnCode != 0)
-				return returnCode;
-		}
-		returnCode = pg_fsync(VfdCache[file].fd);
-		if (returnCode == 0)
-			VfdCache[file].fdstate &= ~FD_DIRTY;
-	}
-
-	return returnCode;
-}
-
-/*
- * FileMarkDirty --- mark a file as needing fsync at transaction commit.
- *
- * Since FileWrite marks the file dirty, this routine is not needed in
- * normal use.	It is called when the buffer manager detects that some other
- * backend has written out a shared buffer that this backend dirtied (but
- * didn't write) in the current xact.  In that scenario, we need to fsync
- * the file before we can commit.  We cannot assume that the other backend
- * has fsync'd the file yet; we need to do our own fsync to ensure that
- * (a) the disk page is written and (b) this backend's commit is delayed
- * until the write is complete.
- *
- * Note we are assuming that an fsync issued by this backend will write
- * kernel disk buffers that were dirtied by another backend.  Furthermore,
- * it doesn't matter whether we currently have the file physically open;
- * we must fsync even if we have to re-open the file to do it.
- */
-void
-FileMarkDirty(File file)
-{
-	Assert(FileIsValid(file));
-
-	DO_DB(elog(LOG, "FileMarkDirty: %d (%s)",
-			   file, VfdCache[file].fileName));
-
-	VfdCache[file].fdstate |= FD_DIRTY;
-}
-
 
 /*
  * Routines that want to use stdio (ie, FILE*) should use AllocateFile
@@ -1142,7 +1017,6 @@ FileMarkDirty(File file)
  *
  * Ideally this should be the *only* direct call of fopen() in the backend.
  */
-
 FILE *
 AllocateFile(char *name, char *mode)
 {
@@ -1229,12 +1103,6 @@ closeAllVfds(void)
  * exit (it doesn't particularly care which).  All still-open temporary-file
  * VFDs are closed, which also causes the underlying files to be deleted.
  * Furthermore, all "allocated" stdio files are closed.
- *
- * This routine is not involved in fsync'ing non-temporary files at xact
- * commit; that is done by FileSync under control of the buffer manager.
- * During a commit, that is done *before* control gets here.  If we still
- * have any needs-fsync bits set when we get here, we assume this is abort
- * and clear them.
  */
 void
 AtEOXact_Files(void)
@@ -1249,8 +1117,6 @@ AtEOXact_Files(void)
 			if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
 				VfdCache[i].fileName != NULL)
 				FileClose(i);
-			else
-				VfdCache[i].fdstate &= ~FD_DIRTY;
 		}
 	}
 
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 978d85d4868ab5b710088940df861ec5347d994a..25051a9799cabaf80fb79fe8a882a748b76f9fd0 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.91 2002/06/20 20:29:35 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.92 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -381,16 +381,7 @@ mdclose_fd(int fd)
 
 		/* if not closed already */
 		if (v->mdfd_vfd >= 0)
-		{
-			/*
-			 * We sync the file descriptor so that we don't need to reopen
-			 * it at transaction commit to force changes to disk.  (This
-			 * is not really optional, because we are about to forget that
-			 * the file even exists...)
-			 */
-			FileSync(v->mdfd_vfd);
 			FileClose(v->mdfd_vfd);
-		}
 		/* Now free vector */
 		v = v->mdfd_chain;
 		if (ov != &Md_fdvec[fd])
@@ -403,16 +394,7 @@ mdclose_fd(int fd)
 	if (v != (MdfdVec *) NULL)
 	{
 		if (v->mdfd_vfd >= 0)
-		{
-			/*
-			 * We sync the file descriptor so that we don't need to reopen
-			 * it at transaction commit to force changes to disk.  (This
-			 * is not really optional, because we are about to forget that
-			 * the file even exists...)
-			 */
-			FileSync(v->mdfd_vfd);
 			FileClose(v->mdfd_vfd);
-		}
 	}
 #endif
 
@@ -497,56 +479,16 @@ mdwrite(Relation reln, BlockNumber blocknum, char *buffer)
 	return SM_SUCCESS;
 }
 
-/*
- *	mdflush() -- Synchronously write a block to disk.
- *
- *		This is exactly like mdwrite(), but doesn't return until the file
- *		system buffer cache has been flushed.
- */
-int
-mdflush(Relation reln, BlockNumber blocknum, char *buffer)
-{
-	int			status;
-	long		seekpos;
-	MdfdVec    *v;
-
-	v = _mdfd_getseg(reln, blocknum);
-
-#ifndef LET_OS_MANAGE_FILESIZE
-	seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));
-#ifdef DIAGNOSTIC
-	if (seekpos >= BLCKSZ * RELSEG_SIZE)
-		elog(FATAL, "seekpos too big!");
-#endif
-#else
-	seekpos = (long) (BLCKSZ * (blocknum));
-#endif
-
-	if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
-		return SM_FAIL;
-
-	/* write and sync the block */
-	status = SM_SUCCESS;
-	if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ
-		|| FileSync(v->mdfd_vfd) < 0)
-		status = SM_FAIL;
-
-	return status;
-}
-
 /*
  *	mdblindwrt() -- Write a block to disk blind.
  *
- *		We have to be able to do this using only the name and OID of
- *		the database and relation in which the block belongs.  Otherwise
- *		this is much like mdwrite().  If dofsync is TRUE, then we fsync
- *		the file, making it more like mdflush().
+ *		We have to be able to do this using only the rnode of the relation
+ *		in which the block belongs.  Otherwise this is much like mdwrite().
  */
 int
 mdblindwrt(RelFileNode rnode,
 		   BlockNumber blkno,
-		   char *buffer,
-		   bool dofsync)
+		   char *buffer)
 {
 	int			status;
 	long		seekpos;
@@ -568,7 +510,6 @@ mdblindwrt(RelFileNode rnode,
 #endif
 
 	errno = 0;
-
 	if (lseek(fd, seekpos, SEEK_SET) != seekpos)
 	{
 		elog(LOG, "mdblindwrt: lseek(%ld) failed: %m", seekpos);
@@ -578,7 +519,7 @@ mdblindwrt(RelFileNode rnode,
 
 	status = SM_SUCCESS;
 
-	/* write and optionally sync the block */
+	/* write the block */
 	errno = 0;
 	if (write(fd, buffer, BLCKSZ) != BLCKSZ)
 	{
@@ -598,54 +539,6 @@ mdblindwrt(RelFileNode rnode,
 	return status;
 }
 
-/*
- *	mdmarkdirty() -- Mark the specified block "dirty" (ie, needs fsync).
- *
- *		Returns SM_SUCCESS or SM_FAIL.
- */
-int
-mdmarkdirty(Relation reln, BlockNumber blkno)
-{
-	MdfdVec    *v;
-
-	v = _mdfd_getseg(reln, blkno);
-
-	FileMarkDirty(v->mdfd_vfd);
-
-	return SM_SUCCESS;
-}
-
-/*
- *	mdblindmarkdirty() -- Mark the specified block "dirty" (ie, needs fsync).
- *
- *		We have to be able to do this using only the name and OID of
- *		the database and relation in which the block belongs.  Otherwise
- *		this is much like mdmarkdirty().  However, we do the fsync immediately
- *		rather than building md/fd datastructures to postpone it till later.
- */
-int
-mdblindmarkdirty(RelFileNode rnode,
-				 BlockNumber blkno)
-{
-	int			status;
-	int			fd;
-
-	fd = _mdfd_blind_getseg(rnode, blkno);
-
-	if (fd < 0)
-		return SM_FAIL;
-
-	status = SM_SUCCESS;
-
-	if (pg_fsync(fd) < 0)
-		status = SM_FAIL;
-
-	if (close(fd) < 0)
-		status = SM_FAIL;
-
-	return status;
-}
-
 /*
  *	mdnblocks() -- Get the number of blocks stored in a relation.
  *
@@ -796,61 +689,36 @@ mdtruncate(Relation reln, BlockNumber nblocks)
 /*
  *	mdcommit() -- Commit a transaction.
  *
- *		All changes to magnetic disk relations must be forced to stable
- *		storage.  This routine makes a pass over the private table of
- *		file descriptors.  Any descriptors to which we have done writes,
- *		but not synced, are synced here.
- *
  *		Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  */
 int
-mdcommit()
+mdcommit(void)
 {
-	int			i;
-	MdfdVec    *v;
-
-	for (i = 0; i < CurFd; i++)
-	{
-		v = &Md_fdvec[i];
-		if (v->mdfd_flags & MDFD_FREE)
-			continue;
-		/* Sync the file entry */
-#ifndef LET_OS_MANAGE_FILESIZE
-		for (; v != (MdfdVec *) NULL; v = v->mdfd_chain)
-#else
-		if (v != (MdfdVec *) NULL)
-#endif
-		{
-			if (FileSync(v->mdfd_vfd) < 0)
-				return SM_FAIL;
-		}
-	}
-
+	/*
+	 * We don't actually have to do anything here...
+	 */
 	return SM_SUCCESS;
 }
 
 /*
  *	mdabort() -- Abort a transaction.
  *
- *		Changes need not be forced to disk at transaction abort.  We mark
- *		all file descriptors as clean here.  Always returns SM_SUCCESS.
+ *		Changes need not be forced to disk at transaction abort.
  */
 int
-mdabort()
+mdabort(void)
 {
 	/*
-	 * We don't actually have to do anything here.  fd.c will discard
-	 * fsync-needed bits in its AtEOXact_Files() routine.
+	 * We don't actually have to do anything here...
 	 */
 	return SM_SUCCESS;
 }
 
 /*
- *	mdsync() -- Sync storage.
- *
+ *	mdsync() -- Sync previous writes to stable storage.
  */
 int
-mdsync()
+mdsync(void)
 {
 	sync();
 	if (IsUnderPostmaster)
@@ -861,11 +729,9 @@ mdsync()
 
 /*
  *	_fdvec_alloc () -- grab a free (or new) md file descriptor vector.
- *
  */
-static
-int
-_fdvec_alloc()
+static int
+_fdvec_alloc(void)
 {
 	MdfdVec    *nvec;
 	int			fdvec,
diff --git a/src/backend/storage/smgr/mm.c b/src/backend/storage/smgr/mm.c
index 89396d173c9966ba5820ee10a619d8446e6fc9bf..739e938fe286e6e8c0a02929d6a331c0e80b18cb 100644
--- a/src/backend/storage/smgr/mm.c
+++ b/src/backend/storage/smgr/mm.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.31 2002/06/20 20:29:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.32 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,7 +81,7 @@ static HTAB *MMCacheHT;
 static HTAB *MMRelCacheHT;
 
 int
-mminit()
+mminit(void)
 {
 	char	   *mmcacheblk;
 	int			mmsize = 0;
@@ -151,7 +151,7 @@ mminit()
 }
 
 int
-mmshutdown()
+mmshutdown(void)
 {
 	return SM_SUCCESS;
 }
@@ -442,31 +442,16 @@ mmwrite(Relation reln, BlockNumber blocknum, char *buffer)
 	return SM_SUCCESS;
 }
 
-/*
- *	mmflush() -- Synchronously write a block to stable storage.
- *
- *		For main-memory relations, this is exactly equivalent to mmwrite().
- */
-int
-mmflush(Relation reln, BlockNumber blocknum, char *buffer)
-{
-	return mmwrite(reln, blocknum, buffer);
-}
-
 /*
  *	mmblindwrt() -- Write a block to stable storage blind.
  *
- *		We have to be able to do this using only the name and OID of
- *		the database and relation in which the block belongs.
+ *		We have to be able to do this using only the rnode of the relation
+ *		in which the block belongs.  Otherwise this is much like mmwrite().
  */
 int
-mmblindwrt(char *dbstr,
-		   char *relstr,
-		   Oid dbid,
-		   Oid relid,
+mmblindwrt(RelFileNode rnode,
 		   BlockNumber blkno,
-		   char *buffer,
-		   bool dofsync)
+		   char *buffer)
 {
 	return SM_FAIL;
 }
@@ -512,7 +497,7 @@ mmnblocks(Relation reln)
  *		Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  */
 int
-mmcommit()
+mmcommit(void)
 {
 	return SM_SUCCESS;
 }
@@ -522,7 +507,7 @@ mmcommit()
  */
 
 int
-mmabort()
+mmabort(void)
 {
 	return SM_SUCCESS;
 }
@@ -536,7 +521,7 @@ mmabort()
  *		manager will use.
  */
 int
-MMShmemSize()
+MMShmemSize(void)
 {
 	int			size = 0;
 
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index a7fb23b4427167ab170645af9c461d6075b650a0..252781d9c3fbbccf436e953980635a3b2fcd4cfb 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.57 2002/06/20 20:29:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.58 2002/08/06 02:36:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,12 +40,8 @@ typedef struct f_smgr
 										  char *buffer);
 	int			(*smgr_write) (Relation reln, BlockNumber blocknum,
 										   char *buffer);
-	int			(*smgr_flush) (Relation reln, BlockNumber blocknum,
-										   char *buffer);
 	int			(*smgr_blindwrt) (RelFileNode rnode, BlockNumber blkno,
-											  char *buffer, bool dofsync);
-	int			(*smgr_markdirty) (Relation reln, BlockNumber blkno);
-	int			(*smgr_blindmarkdirty) (RelFileNode, BlockNumber blkno);
+											  char *buffer);
 	BlockNumber (*smgr_nblocks) (Relation reln);
 	BlockNumber (*smgr_truncate) (Relation reln, BlockNumber nblocks);
 	int			(*smgr_commit) (void);	/* may be NULL */
@@ -62,15 +58,15 @@ static f_smgr smgrsw[] = {
 
 	/* magnetic disk */
 	{mdinit, NULL, mdcreate, mdunlink, mdextend, mdopen, mdclose,
-		mdread, mdwrite, mdflush, mdblindwrt, mdmarkdirty, mdblindmarkdirty,
+		mdread, mdwrite, mdblindwrt,
 		mdnblocks, mdtruncate, mdcommit, mdabort, mdsync
 	},
 
 #ifdef STABLE_MEMORY_STORAGE
 	/* main memory */
 	{mminit, mmshutdown, mmcreate, mmunlink, mmextend, mmopen, mmclose,
-		mmread, mmwrite, mmflush, mmblindwrt, mmmarkdirty, mmblindmarkdirty,
-	mmnblocks, NULL, mmcommit, mmabort},
+		mmread, mmwrite, mmblindwrt,
+		mmnblocks, NULL, mmcommit, mmabort, NULL},
 #endif
 };
 
@@ -110,6 +106,7 @@ typedef struct PendingRelDelete
 {
 	RelFileNode relnode;		/* relation that may need to be deleted */
 	int16		which;			/* which storage manager? */
+	bool		isTemp;			/* is it a temporary relation? */
 	bool		atCommit;		/* T=delete at commit; F=delete at abort */
 	struct PendingRelDelete *next;		/* linked-list link */
 } PendingRelDelete;
@@ -123,7 +120,7 @@ static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
  *
  */
 int
-smgrinit()
+smgrinit(void)
 {
 	int			i;
 
@@ -181,6 +178,7 @@ smgrcreate(int16 which, Relation reln)
 		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
 	pending->relnode = reln->rd_node;
 	pending->which = which;
+	pending->isTemp = reln->rd_istemp;
 	pending->atCommit = false;	/* delete if abort */
 	pending->next = pendingDeletes;
 	pendingDeletes = pending;
@@ -208,6 +206,7 @@ smgrunlink(int16 which, Relation reln)
 		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
 	pending->relnode = reln->rd_node;
 	pending->which = which;
+	pending->isTemp = reln->rd_istemp;
 	pending->atCommit = true;	/* delete if commit */
 	pending->next = pendingDeletes;
 	pendingDeletes = pending;
@@ -312,8 +311,10 @@ smgrread(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
 /*
  *	smgrwrite() -- Write the supplied buffer out.
  *
- *		This is not a synchronous write -- the interface for that is
- *		smgrflush().  The buffer is written out via the appropriate
+ *		This is not a synchronous write -- the block is not necessarily
+ *		on disk at return, only dumped out to the kernel.
+ *
+ *		The buffer is written out via the appropriate
  *		storage manager.  This routine returns SM_SUCCESS or aborts
  *		the current transaction.
  */
@@ -331,23 +332,6 @@ smgrwrite(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
 	return status;
 }
 
-/*
- *	smgrflush() -- A synchronous smgrwrite().
- */
-int
-smgrflush(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
-{
-	int			status;
-
-	status = (*(smgrsw[which].smgr_flush)) (reln, blocknum, buffer);
-
-	if (status == SM_FAIL)
-		elog(ERROR, "cannot flush block %d of %s to stable store: %m",
-			 blocknum, RelationGetRelationName(reln));
-
-	return status;
-}
-
 /*
  *	smgrblindwrt() -- Write a page out blind.
  *
@@ -357,20 +341,18 @@ smgrflush(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
  *		that has not yet committed, which created a new relation.  In
  *		this case, the buffer manager will call smgrblindwrt() with
  *		the name and OID of the database and the relation to which the
- *		buffer belongs.  Every storage manager must be able to force
- *		this page down to stable storage in this circumstance.	The
- *		write should be synchronous if dofsync is true.
+ *		buffer belongs.  Every storage manager must be able to write
+ *		this page out to stable storage in this circumstance.
  */
 int
 smgrblindwrt(int16 which,
 			 RelFileNode rnode,
 			 BlockNumber blkno,
-			 char *buffer,
-			 bool dofsync)
+			 char *buffer)
 {
 	int			status;
 
-	status = (*(smgrsw[which].smgr_blindwrt)) (rnode, blkno, buffer, dofsync);
+	status = (*(smgrsw[which].smgr_blindwrt)) (rnode, blkno, buffer);
 
 	if (status == SM_FAIL)
 		elog(ERROR, "cannot write block %d of %u/%u blind: %m",
@@ -379,53 +361,6 @@ smgrblindwrt(int16 which,
 	return status;
 }
 
-/*
- *	smgrmarkdirty() -- Mark a page dirty (needs fsync).
- *
- *		Mark the specified page as needing to be fsync'd before commit.
- *		Ordinarily, the storage manager will do this implicitly during
- *		smgrwrite().  However, the buffer manager may discover that some
- *		other backend has written a buffer that we dirtied in the current
- *		transaction.  In that case, we still need to fsync the file to be
- *		sure the page is down to disk before we commit.
- */
-int
-smgrmarkdirty(int16 which,
-			  Relation reln,
-			  BlockNumber blkno)
-{
-	int			status;
-
-	status = (*(smgrsw[which].smgr_markdirty)) (reln, blkno);
-
-	if (status == SM_FAIL)
-		elog(ERROR, "cannot mark block %d of %s: %m",
-			 blkno, RelationGetRelationName(reln));
-
-	return status;
-}
-
-/*
- *	smgrblindmarkdirty() -- Mark a page dirty, "blind".
- *
- *		Just like smgrmarkdirty, except we don't have a reldesc.
- */
-int
-smgrblindmarkdirty(int16 which,
-				   RelFileNode rnode,
-				   BlockNumber blkno)
-{
-	int			status;
-
-	status = (*(smgrsw[which].smgr_blindmarkdirty)) (rnode, blkno);
-
-	if (status == SM_FAIL)
-		elog(ERROR, "cannot mark block %d of %u/%u blind: %m",
-			 blkno, rnode.tblNode, rnode.relNode);
-
-	return status;
-}
-
 /*
  *	smgrnblocks() -- Calculate the number of POSTGRES blocks in the
  *					 supplied relation.
@@ -504,7 +439,7 @@ smgrDoPendingDeletes(bool isCommit)
 			 * any in the commit case, but there can be in the abort
 			 * case).
 			 */
-			DropRelFileNodeBuffers(pending->relnode);
+			DropRelFileNodeBuffers(pending->relnode, pending->isTemp);
 
 			/*
 			 * Tell the free space map to forget this relation.  It won't
@@ -531,11 +466,13 @@ smgrDoPendingDeletes(bool isCommit)
 }
 
 /*
- *	smgrcommit(), smgrabort() -- Commit or abort changes made during the
- *								 current transaction.
+ *	smgrcommit() -- Prepare to commit changes made during the current
+ *					transaction.
+ *
+ * This is called before we actually commit.
  */
 int
-smgrcommit()
+smgrcommit(void)
 {
 	int			i;
 
@@ -553,8 +490,11 @@ smgrcommit()
 	return SM_SUCCESS;
 }
 
+/*
+ *	smgrabort() -- Abort changes made during the current transaction.
+ */
 int
-smgrabort()
+smgrabort(void)
 {
 	int			i;
 
@@ -572,8 +512,11 @@ smgrabort()
 	return SM_SUCCESS;
 }
 
+/*
+ * Sync files to disk at checkpoint time.
+ */
 int
-smgrsync()
+smgrsync(void)
 {
 	int			i;
 
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index f1ed253d7110ce9aa10420a4d68e9a222498fa80..f6c11206bd81fcde95d3bc7572d8b6f7d1f704f7 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.170 2002/08/04 18:12:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.171 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,7 @@
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_attrdef.h"
@@ -94,13 +95,6 @@ static HTAB *RelationSysNameCache;
  */
 static HTAB *RelationNodeCache;
 
-/*
- * newlyCreatedRelns -
- *	  relations created during this transaction. We need to keep track of
- *	  these.
- */
-static List *newlyCreatedRelns = NIL;
-
 /*
  * This flag is false until we have prepared the critical relcache entries
  * that are needed to do indexscans on the tables read by relcache building.
@@ -865,9 +859,12 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	RelationSetReferenceCount(relation, 1);
 
 	/*
-	 * normal relations are not nailed into the cache
+	 * normal relations are not nailed into the cache; nor can a pre-existing
+	 * relation be new or temp.
 	 */
 	relation->rd_isnailed = false;
+	relation->rd_isnew = false;
+	relation->rd_istemp = false;
 
 	/*
 	 * initialize the tuple descriptor (relation->rd_att).
@@ -957,9 +954,6 @@ RelationInitIndexAccessInfo(Relation relation)
 	ReleaseSysCache(tuple);
 	relation->rd_index = iform;
 
-	/* this field is now kinda redundant... */
-	relation->rd_uniqueindex = iform->indisunique;
-
 	/*
 	 * Make a copy of the pg_am entry for the index's access method
 	 */
@@ -1359,9 +1353,12 @@ formrdesc(const char *relationName,
 	RelationSetReferenceCount(relation, 1);
 
 	/*
-	 * all entries built with this routine are nailed-in-cache
+	 * all entries built with this routine are nailed-in-cache; none are
+	 * for new or temp relations.
 	 */
 	relation->rd_isnailed = true;
+	relation->rd_isnew = false;
+	relation->rd_istemp = false;
 
 	/*
 	 * initialize relation tuple form
@@ -1603,7 +1600,9 @@ RelationClose(Relation relation)
 	RelationDecrementReferenceCount(relation);
 
 #ifdef RELCACHE_FORCE_RELEASE
-	if (RelationHasReferenceCountZero(relation) && !relation->rd_myxactonly)
+	if (RelationHasReferenceCountZero(relation) &&
+		!relation->rd_isnew &&
+		!relation->rd_istemp)
 		RelationClearRelation(relation, false);
 #endif
 }
@@ -1734,13 +1733,14 @@ RelationClearRelation(Relation relation, bool rebuild)
 	{
 		/*
 		 * When rebuilding an open relcache entry, must preserve ref count
-		 * and myxactonly flag.  Also attempt to preserve the tupledesc,
+		 * and new/temp flags.  Also attempt to preserve the tupledesc,
 		 * rewrite rules, and trigger substructures in place. Furthermore
-		 * we save/restore rd_nblocks (in case it is a local relation)
+		 * we save/restore rd_nblocks (in case it is a new/temp relation)
 		 * *and* call RelationGetNumberOfBlocks (in case it isn't).
 		 */
 		int			old_refcnt = relation->rd_refcnt;
-		bool		old_myxactonly = relation->rd_myxactonly;
+		bool		old_isnew = relation->rd_isnew;
+		bool		old_istemp = relation->rd_istemp;
 		TupleDesc	old_att = relation->rd_att;
 		RuleLock   *old_rules = relation->rd_rules;
 		MemoryContext old_rulescxt = relation->rd_rulescxt;
@@ -1763,7 +1763,8 @@ RelationClearRelation(Relation relation, bool rebuild)
 				 buildinfo.i.info_id);
 		}
 		RelationSetReferenceCount(relation, old_refcnt);
-		relation->rd_myxactonly = old_myxactonly;
+		relation->rd_isnew = old_isnew;
+		relation->rd_istemp = old_istemp;
 		if (equalTupleDescs(old_att, relation->rd_att))
 		{
 			FreeTupleDesc(relation->rd_att);
@@ -1810,11 +1811,11 @@ RelationFlushRelation(Relation relation)
 {
 	bool		rebuild;
 
-	if (relation->rd_myxactonly)
+	if (relation->rd_isnew || relation->rd_istemp)
 	{
 		/*
-		 * Local rels should always be rebuilt, not flushed; the relcache
-		 * entry must live until RelationPurgeLocalRelation().
+		 * New and temp relcache entries must always be rebuilt, not
+		 * flushed; else we'd forget those two important status bits.
 		 */
 		rebuild = true;
 	}
@@ -1830,11 +1831,10 @@ RelationFlushRelation(Relation relation)
 }
 
 /*
- * RelationForgetRelation -
+ * RelationForgetRelation - unconditionally remove a relcache entry
  *
- *		   RelationClearRelation + if the relation is myxactonly then
- *		   remove the relation descriptor from the newly created
- *		   relation list.
+ *		   External interface for destroying a relcache entry when we
+ *		   drop the relation.
  */
 void
 RelationForgetRelation(Oid rid)
@@ -1849,31 +1849,6 @@ RelationForgetRelation(Oid rid)
 	if (!RelationHasReferenceCountZero(relation))
 		elog(ERROR, "RelationForgetRelation: relation %u is still open", rid);
 
-	/* If local, remove from list */
-	if (relation->rd_myxactonly)
-	{
-		List	   *curr;
-		List	   *prev = NIL;
-
-		foreach(curr, newlyCreatedRelns)
-		{
-			Relation	reln = lfirst(curr);
-
-			Assert(reln != NULL && reln->rd_myxactonly);
-			if (RelationGetRelid(reln) == rid)
-				break;
-			prev = curr;
-		}
-		if (curr == NIL)
-			elog(ERROR, "Local relation %s not found in list",
-				 RelationGetRelationName(relation));
-		if (prev == NIL)
-			newlyCreatedRelns = lnext(newlyCreatedRelns);
-		else
-			lnext(prev) = lnext(curr);
-		pfree(curr);
-	}
-
 	/* Unconditionally destroy the relcache entry */
 	RelationClearRelation(relation, false);
 }
@@ -1909,7 +1884,7 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
  *	 and rebuild those with positive reference counts.
  *
  *	 This is currently used only to recover from SI message buffer overflow,
- *	 so we do not touch transaction-local relations; they cannot be targets
+ *	 so we do not touch new-in-transaction relations; they cannot be targets
  *	 of cross-backend SI updates (and our own updates now go through a
  *	 separate linked list that isn't limited by the SI message buffer size).
  *
@@ -1940,13 +1915,13 @@ RelationCacheInvalidate(void)
 	{
 		relation = idhentry->reldesc;
 
-		/* Ignore xact-local relations, since they are never SI targets */
-		if (relation->rd_myxactonly)
+		/* Ignore new relations, since they are never SI targets */
+		if (relation->rd_isnew)
 			continue;
 
 		relcacheInvalsReceived++;
 
-		if (RelationHasReferenceCountZero(relation))
+		if (RelationHasReferenceCountZero(relation) && !relation->rd_istemp)
 		{
 			/* Delete this entry immediately */
 			RelationClearRelation(relation, false);
@@ -1968,37 +1943,16 @@ RelationCacheInvalidate(void)
 }
 
 /*
- * AtEOXactRelationCache
+ * AtEOXact_RelationCache
  *
  *	Clean up the relcache at transaction commit or abort.
- *
- *	During transaction abort, we must reset relcache entry ref counts
- *	to their normal not-in-a-transaction state.  A ref count may be
- *	too high because some routine was exited by elog() between
- *	incrementing and decrementing the count.
- *
- *	During commit, we should not have to do this, but it's useful to
- *	check that the counts are correct to catch missed relcache closes.
- *	Since that's basically a debugging thing, only pay the cost when
- *	assert checking is enabled.
- *
- *	In bootstrap mode, forget the debugging checks --- the bootstrap code
- *	expects relations to stay open across start/commit transaction calls.
  */
 void
-AtEOXactRelationCache(bool commit)
+AtEOXact_RelationCache(bool commit)
 {
 	HASH_SEQ_STATUS status;
 	RelIdCacheEnt *idhentry;
 
-#ifdef USE_ASSERT_CHECKING
-	if (commit && IsBootstrapProcessingMode())
-		return;
-#else
-	if (commit)
-		return;
-#endif
-
 	hash_seq_init(&status, RelationIdCache);
 
 	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
@@ -2006,11 +1960,45 @@ AtEOXactRelationCache(bool commit)
 		Relation	relation = idhentry->reldesc;
 		int			expected_refcnt;
 
+		/*
+		 * Is it a relation created in the current transaction?
+		 *
+		 * During commit, reset the flag to false, since we are now out of the
+		 * creating transaction.  During abort, simply delete the relcache
+		 * entry --- it isn't interesting any longer.
+		 */
+		if (relation->rd_isnew)
+		{
+			if (commit)
+				relation->rd_isnew = false;
+			else
+			{
+				RelationClearRelation(relation, false);
+				continue;
+			}
+		}
+
+		/*
+		 * During transaction abort, we must also reset relcache entry ref
+		 * counts to their normal not-in-a-transaction state.  A ref count may
+		 * be too high because some routine was exited by elog() between
+		 * incrementing and decrementing the count.
+		 *
+		 * During commit, we should not have to do this, but it's still useful
+		 * to check that the counts are correct to catch missed relcache
+		 * closes.
+		 *
+		 * In bootstrap mode, do NOT reset the refcnt nor complain that it's
+		 * nonzero --- the bootstrap code expects relations to stay open
+		 * across start/commit transaction calls.  (That seems bogus, but it's
+		 * not worth fixing.)
+		 */
 		expected_refcnt = relation->rd_isnailed ? 1 : 0;
 
 		if (commit)
 		{
-			if (relation->rd_refcnt != expected_refcnt)
+			if (relation->rd_refcnt != expected_refcnt &&
+				!IsBootstrapProcessingMode())
 			{
 				elog(WARNING, "Relcache reference leak: relation \"%s\" has refcnt %d instead of %d",
 					 RelationGetRelationName(relation),
@@ -2055,10 +2043,11 @@ RelationBuildLocalRelation(const char *relname,
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
 	/*
-	 * allocate a new relation descriptor.
+	 * allocate a new relation descriptor and fill in basic state fields.
 	 */
 	rel = (Relation) palloc(sizeof(RelationData));
 	MemSet((char *) rel, 0, sizeof(RelationData));
+
 	rel->rd_targblock = InvalidBlockNumber;
 
 	/* make sure relation is marked as having no open file yet */
@@ -2066,6 +2055,12 @@ RelationBuildLocalRelation(const char *relname,
 
 	RelationSetReferenceCount(rel, 1);
 
+	/* it's being created in this transaction */
+	rel->rd_isnew = true;
+
+	/* is it a temporary relation? */
+	rel->rd_istemp = isTempNamespace(relnamespace);
+
 	/*
 	 * nail the reldesc if this is a bootstrap create reln and we may need
 	 * it in the cache later on in the bootstrap process so we don't ever
@@ -2121,17 +2116,6 @@ RelationBuildLocalRelation(const char *relname,
 	 */
 	RelationCacheInsert(rel);
 
-	/*
-	 * we've just created the relation. It is invisible to anyone else
-	 * before the transaction is committed. Setting rd_myxactonly allows
-	 * us to use the local buffer manager for select/insert/etc before the
-	 * end of transaction. (We also need to keep track of relations
-	 * created during a transaction and do the necessary clean up at the
-	 * end of the transaction.)				- ay 3/95
-	 */
-	rel->rd_myxactonly = true;
-	newlyCreatedRelns = lcons(rel, newlyCreatedRelns);
-
 	/*
 	 * done building relcache entry.
 	 */
@@ -2140,38 +2124,6 @@ RelationBuildLocalRelation(const char *relname,
 	return rel;
 }
 
-/*
- * RelationPurgeLocalRelation -
- *	  find all the Relation descriptors marked rd_myxactonly and reset them.
- *	  This should be called at the end of a transaction (commit/abort) when
- *	  the "local" relations will become visible to others and the multi-user
- *	  buffer pool should be used.
- */
-void
-RelationPurgeLocalRelation(bool xactCommitted)
-{
-	while (newlyCreatedRelns)
-	{
-		List	   *l = newlyCreatedRelns;
-		Relation	reln = lfirst(l);
-
-		newlyCreatedRelns = lnext(newlyCreatedRelns);
-		pfree(l);
-
-		Assert(reln != NULL && reln->rd_myxactonly);
-
-		reln->rd_myxactonly = false;	/* mark it not on list anymore */
-
-		/*
-		 * XXX while we clearly must throw out new Relation entries at
-		 * xact abort, it's not clear why we need to do it at commit.
-		 * Could this be improved?
-		 */
-		if (!IsBootstrapProcessingMode())
-			RelationClearRelation(reln, false);
-	}
-}
-
 /*
  *		RelationCacheInitialize
  *
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4b661f53d3249ad8d370133e8724f8d556282210..132fef26c882d7529b9ff527aaace3bb13e7fc5b 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xlog.h,v 1.33 2002/08/05 01:24:16 thomas Exp $
+ * $Id: xlog.h,v 1.34 2002/08/06 02:36:35 tgl Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -182,6 +182,7 @@ extern StartUpID ThisStartUpID; /* current SUI */
 extern bool InRecovery;
 extern XLogRecPtr MyLastRecPtr;
 extern bool MyXactMadeXLogEntry;
+extern bool MyXactMadeTempRelUpdate;
 extern XLogRecPtr ProcLastRecEnd;
 
 /* these variables are GUC parameters related to XLOG */
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index bd0907ed95281008d2b3af078928c45f11e8255f..6f8c4ad841d012ce3242a32fad28716f85d7d784 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.57 2002/06/20 20:29:52 momjian Exp $
+ * $Id: buf_internals.h,v 1.58 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,6 +149,15 @@ typedef struct _bmtrace
 #endif   /* BMTRACE */
 
 
+/* counters in buf_init.c */
+extern long int	ReadBufferCount;
+extern long int	ReadLocalBufferCount;
+extern long int	BufferHitCount;
+extern long int	LocalBufferHitCount;
+extern long int	BufferFlushCount;
+extern long int	LocalBufferFlushCount;
+
+
 /*
  * Bufmgr Interface:
  */
@@ -177,8 +186,6 @@ extern BufferDesc *LocalBufferDescriptors;
 extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum,
 				 bool *foundPtr);
 extern void	WriteLocalBuffer(Buffer buffer, bool release);
-extern int	FlushLocalBuffer(Buffer buffer, bool sync, bool release);
-extern void LocalBufferSync(void);
-extern void ResetLocalBufferPool(void);
+extern void AtEOXact_LocalBuffers(bool isCommit);
 
 #endif   /* BUFMGR_INTERNALS_H */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index a6952fa1f69cb921ab36096469393e62a5c25dfa..7aebaa73da62cd456ea82bbedc64ff94a999db94 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bufmgr.h,v 1.61 2002/07/02 05:47:37 momjian Exp $
+ * $Id: bufmgr.h,v 1.62 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,20 +152,18 @@ extern void	WriteBuffer(Buffer buffer);
 extern void	WriteNoReleaseBuffer(Buffer buffer);
 extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
 					 BlockNumber blockNum);
-extern int	FlushBuffer(Buffer buffer, bool sync, bool release);
 
 extern void InitBufferPool(void);
 extern void InitBufferPoolAccess(void);
 extern char *ShowBufferUsage(void);
 extern void ResetBufferUsage(void);
-extern void ResetBufferPool(bool isCommit);
-extern bool BufferPoolCheckLeak(void);
+extern void AtEOXact_Buffers(bool isCommit);
 extern void FlushBufferPool(void);
 extern BlockNumber BufferGetBlockNumber(Buffer buffer);
 extern BlockNumber RelationGetNumberOfBlocks(Relation relation);
 extern int	FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock);
 extern void DropRelationBuffers(Relation rel);
-extern void DropRelFileNodeBuffers(RelFileNode rnode);
+extern void DropRelFileNodeBuffers(RelFileNode rnode, bool istemp);
 extern void DropBuffers(Oid dbid);
 #ifdef NOT_USED
 extern void PrintPinnedBufs(void);
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 13f5100c66181f8110ef59dcb1a150cc06363cc4..a13cec41ea6827dbc137737e9c15ae6a38f44923 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fd.h,v 1.35 2002/06/20 20:29:52 momjian Exp $
+ * $Id: fd.h,v 1.36 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,8 +62,6 @@ extern int	FileRead(File file, char *buffer, int amount);
 extern int	FileWrite(File file, char *buffer, int amount);
 extern long FileSeek(File file, long offset, int whence);
 extern int	FileTruncate(File file, long offset);
-extern int	FileSync(File file);
-extern void FileMarkDirty(File file);
 
 /* Operations that allow use of regular stdio --- USE WITH CAUTION */
 extern FILE *AllocateFile(char *name, char *mode);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 474bfbc9326cb2e4fbcfee5f6b16565779628927..d5a96ea0c9979af6130ea0df0454c9243e90eb79 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: smgr.h,v 1.35 2002/06/20 20:29:52 momjian Exp $
+ * $Id: smgr.h,v 1.36 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,13 +36,8 @@ extern int smgrread(int16 which, Relation reln, BlockNumber blocknum,
 		 char *buffer);
 extern int smgrwrite(int16 which, Relation reln, BlockNumber blocknum,
 		  char *buffer);
-extern int smgrflush(int16 which, Relation reln, BlockNumber blocknum,
-		  char *buffer);
 extern int smgrblindwrt(int16 which, RelFileNode rnode,
-			 BlockNumber blkno, char *buffer, bool dofsync);
-extern int smgrblindmarkdirty(int16 which, RelFileNode rnode,
-				   BlockNumber blkno);
-extern int	smgrmarkdirty(int16 which, Relation reln, BlockNumber blkno);
+			 BlockNumber blkno, char *buffer);
 extern BlockNumber smgrnblocks(int16 which, Relation reln);
 extern BlockNumber smgrtruncate(int16 which, Relation reln,
 			 BlockNumber nblocks);
@@ -67,11 +62,7 @@ extern int	mdopen(Relation reln);
 extern int	mdclose(Relation reln);
 extern int	mdread(Relation reln, BlockNumber blocknum, char *buffer);
 extern int	mdwrite(Relation reln, BlockNumber blocknum, char *buffer);
-extern int	mdflush(Relation reln, BlockNumber blocknum, char *buffer);
-extern int	mdmarkdirty(Relation reln, BlockNumber blkno);
-extern int mdblindwrt(RelFileNode rnode, BlockNumber blkno,
-		   char *buffer, bool dofsync);
-extern int	mdblindmarkdirty(RelFileNode rnode, BlockNumber blkno);
+extern int	mdblindwrt(RelFileNode rnode, BlockNumber blkno, char *buffer);
 extern BlockNumber mdnblocks(Relation reln);
 extern BlockNumber mdtruncate(Relation reln, BlockNumber nblocks);
 extern int	mdcommit(void);
@@ -87,13 +78,7 @@ extern int	mmopen(Relation reln);
 extern int	mmclose(Relation reln);
 extern int	mmread(Relation reln, BlockNumber blocknum, char *buffer);
 extern int	mmwrite(Relation reln, BlockNumber blocknum, char *buffer);
-extern int	mmflush(Relation reln, BlockNumber blocknum, char *buffer);
-extern int mmblindwrt(char *dbname, char *relname, Oid dbid, Oid relid,
-		   BlockNumber blkno, char *buffer,
-		   bool dofsync);
-extern int	mmmarkdirty(Relation reln, BlockNumber blkno);
-extern int mmblindmarkdirty(char *dbname, char *relname, Oid dbid, Oid relid,
-				 BlockNumber blkno);
+extern int	mmblindwrt(RelFileNode rnode, BlockNumber blkno, char *buffer);
 extern BlockNumber mmnblocks(Relation reln);
 extern BlockNumber mmtruncate(Relation reln, BlockNumber nblocks);
 extern int	mmcommit(void);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 3dce1757ed432067881f544b95e3c42494bfcd18..d913f28aba362a36de1aff5ad4cbf6ef55983d88 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.60 2002/06/20 20:29:53 momjian Exp $
+ * $Id: rel.h,v 1.61 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,10 +112,10 @@ typedef struct RelationData
 	BlockNumber rd_targblock;	/* current insertion target block, or
 								 * InvalidBlockNumber */
 	int			rd_refcnt;		/* reference count */
-	bool		rd_myxactonly;	/* rel uses the local buffer mgr */
+	bool		rd_isnew;		/* rel was created in current xact */
+	bool		rd_istemp;		/* rel uses the local buffer mgr */
 	bool		rd_isnailed;	/* rel is nailed in cache */
 	bool		rd_indexfound;	/* true if rd_indexlist is valid */
-	bool		rd_uniqueindex; /* true if rel is a UNIQUE index */
 	Form_pg_class rd_rel;		/* RELATION tuple */
 	TupleDesc	rd_att;			/* tuple descriptor */
 	Oid			rd_id;			/* relation's object id */
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index fd22a65296d8637b0e9f96cc9581aa76dc6ed17a..c04952849129f22f4722f1d5ba7d7d75abdd5495 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relcache.h,v 1.33 2002/08/02 22:36:05 tgl Exp $
+ * $Id: relcache.h,v 1.34 2002/08/06 02:36:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,9 +61,7 @@ extern void RelationIdInvalidateRelationCacheByRelationId(Oid relationId);
 
 extern void RelationCacheInvalidate(void);
 
-extern void RelationPurgeLocalRelation(bool xactComitted);
-
-extern void AtEOXactRelationCache(bool commit);
+extern void AtEOXact_RelationCache(bool commit);
 
 /*
  * Routines to help manage rebuilding of relcache init file