diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 315d813e9202e980b0b99889a79176d73070ac82..5533fa0509c846539452fd5d4ddba0414c84a211 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.74 2000/10/21 15:43:22 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.75 2000/10/23 04:10:05 vadim Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -676,6 +676,7 @@ RecordTransactionCommit()
 	 */
 	leak = BufferPoolCheckLeak();
 
+#ifndef XLOG
 	/*
 	 * If no one shared buffer was changed by this transaction then we
 	 * don't flush shared buffers and don't record commit status.
@@ -686,6 +687,7 @@ RecordTransactionCommit()
 		if (leak)
 			ResetBufferPool(true);
 
+#endif
 		/*
 		 * have the transaction access methods record the status of this
 		 * transaction id in the pg_log relation.
@@ -717,13 +719,14 @@ RecordTransactionCommit()
 			MyLastRecPtr.xlogid = 0;
 			MyLastRecPtr.xrecoff = 0;
 		}
-#endif
+#else
 		/*
 		 * Now write the log info to the disk too.
 		 */
 		leak = BufferPoolCheckLeak();
 		FlushBufferPool();
 	}
+#endif
 
 	if (leak)
 		ResetBufferPool(true);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index bae7af83c3831b955a35ddab96391db5478e98a2..19d7f38c1ef03bfa4fb614d06e14c6ac548fec1b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.19 2000/10/21 15:43:22 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.20 2000/10/23 04:10:05 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -991,6 +991,7 @@ got_record:;
 			nextRecord = (XLogRecord *) ((char *) subrecord + 
 				MAXALIGN(subrecord->xl_len) + SizeOfXLogSubRecord);
 		}
+		record->xl_len = len;
 		EndRecPtr.xlogid = readId;
 		EndRecPtr.xrecoff = readSeg * XLogSegSize + readOff * BLCKSZ +
 			SizeOfXLogPHD + SizeOfXLogSubRecord + 
@@ -1412,7 +1413,9 @@ StartupXLOG()
 				{
 					char	buf[8192];
 
-					sprintf(buf, "REDO @ %u/%u: ", ReadRecPtr.xlogid, ReadRecPtr.xrecoff);
+					sprintf(buf, "REDO @ %u/%u; LSN %u/%u: ", 
+						ReadRecPtr.xlogid, ReadRecPtr.xrecoff,
+						EndRecPtr.xlogid, EndRecPtr.xrecoff);
 					xlog_outrec(buf, record);
 					strcat(buf, " - ");
 					RmgrTable[record->xl_rmid].rm_desc(buf, 
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 13aca31a3e4f481e09b1bb5de20618e278cfa3e0..3c40009422da9bed0d11b6a2125c430b2917ead7 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.36 2000/10/18 05:50:15 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.37 2000/10/23 04:10:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,7 +68,6 @@ bits8	   *BufferLocks;		/* flag bits showing locks I have set */
 BufferTag  *BufferTagLastDirtied;		/* tag buffer had when last
 										 * dirtied by me */
 BufferBlindId  *BufferBlindLastDirtied;
-LockRelId	   *BufferRelidLastDirtied;
 bool		   *BufferDirtiedByMe;	/* T if buf has been dirtied in cur xact */
 
 
@@ -252,7 +251,6 @@ InitBufferPool(IPCKey key)
 	BufferLocks = (bits8 *) calloc(NBuffers, sizeof(bits8));
 	BufferTagLastDirtied = (BufferTag *) calloc(NBuffers, sizeof(BufferTag));
 	BufferBlindLastDirtied = (BufferBlindId *) calloc(NBuffers, sizeof(BufferBlindId));
-	BufferRelidLastDirtied = (LockRelId *) calloc(NBuffers, sizeof(LockRelId));
 	BufferDirtiedByMe = (bool *) calloc(NBuffers, sizeof(bool));
 }
 
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 9161c4852969f5bdf8e37c3b774d5d0109463726..c0a320986ce9c670756ad66280d59ad654a705bf 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.90 2000/10/22 20:20:49 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.91 2000/10/23 04:10:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,10 @@
 #include "storage/smgr.h"
 #include "utils/relcache.h"
 
+#ifdef XLOG
+#include "catalog/pg_database.h"
+#endif
+
 extern SPINLOCK BufMgrLock;
 extern long int ReadBufferCount;
 extern long int ReadLocalBufferCount;
@@ -611,7 +615,6 @@ BufferAlloc(Relation reln,
 	/* record the database name and relation name for this buffer */
 	strcpy(buf->blind.dbname, (DatabaseName) ? DatabaseName : "Recovery");
 	strcpy(buf->blind.relname, RelationGetPhysicalRelationName(reln));
-	buf->relId = reln->rd_lockInfo.lockRelId;
 
 	INIT_BUFFERTAG(&(buf->tag), reln, blockNum);
 	if (!BufTableInsert(buf))
@@ -711,7 +714,6 @@ int
 FlushBuffer(Buffer buffer, bool release)
 {
 	BufferDesc *bufHdr;
-	Oid			bufdb;
 	Relation	bufrel;
 	int			status;
 
@@ -725,10 +727,7 @@ FlushBuffer(Buffer buffer, bool release)
 
 	bufHdr = &BufferDescriptors[buffer - 1];
 
-	bufdb = bufHdr->relId.dbId;
-
-	Assert(bufdb == MyDatabaseId || bufdb == (Oid) NULL);
-	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
+	bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
 	Assert(bufrel != (Relation) NULL);
 
@@ -904,7 +903,7 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 		SpinRelease(BufMgrLock);
 #endif	 /* OPTIMIZE_SINGLE */
 
-		reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[buffer - 1].relId);
+		reln = RelationNodeCacheGetRelation(tagLastDirtied->rnode);
 
 		if (reln == (Relation) NULL)
 		{
@@ -938,7 +937,6 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 	}
 
 	*tagLastDirtied = bufHdr->tag;
-	BufferRelidLastDirtied[buffer - 1] = bufHdr->relId;
 	BufferBlindLastDirtied[buffer - 1] = bufHdr->blind;
 	BufferDirtiedByMe[buffer - 1] = true;
 }
@@ -1010,15 +1008,14 @@ BufferSync()
 			if (RelFileNodeEquals(bufHdr->tag.rnode, BufferTagLastDirtied[i].rnode) &&
 				bufHdr->tag.blockNum == BufferTagLastDirtied[i].blockNum)
 			{
-				Oid		bufrel = bufHdr->relId.relId;
-
 				/*
 				 * Try to find relation for buf.  This could fail, if the
 				 * rel has been flushed from the relcache since we dirtied
 				 * the page.  That should be uncommon, so paying the extra
 				 * cost of a blind write when it happens seems OK.
 				 */
-				reln = RelationIdCacheGetRelation(bufrel);
+				if (!InRecovery)
+					reln = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
 				/*
 				 * We have to pin buffer to keep anyone from stealing it
@@ -1083,8 +1080,6 @@ BufferSync()
 					}
 					else
 					{
-						Assert(RelFileNodeEquals(reln->rd_node,
-									BufferTagLastDirtied[i].rnode));
 						status = smgrwrite(DEFAULT_SMGR, reln,
 										   bufHdr->tag.blockNum,
 										(char *) MAKE_PTR(bufHdr->data));
@@ -1138,7 +1133,7 @@ BufferSync()
 			SpinRelease(BufMgrLock);
 #endif	 /* OPTIMIZE_SINGLE */
 
-			reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[i].relId);
+			reln = RelationNodeCacheGetRelation(BufferTagLastDirtied[i].rnode);
 			if (reln == (Relation) NULL)
 			{
 				status = smgrblindmarkdirty(DEFAULT_SMGR,
@@ -1147,8 +1142,6 @@ BufferSync()
 			}
 			else
 			{
-				Assert(RelFileNodeEquals(reln->rd_node,
-							BufferTagLastDirtied[i].rnode));
 				status = smgrmarkdirty(DEFAULT_SMGR, reln,
 									   BufferTagLastDirtied[i].blockNum);
 
@@ -1420,21 +1413,14 @@ static int
 BufferReplace(BufferDesc *bufHdr)
 {
 	Relation	reln;
-	Oid			bufdb,
-				bufrel;
 	int			status;
 
 	/*
 	 * first try to find the reldesc in the cache, if no luck, don't
 	 * bother to build the reldesc from scratch, just do a blind write.
 	 */
-	bufdb = bufHdr->relId.dbId;
-	bufrel = bufHdr->relId.relId;
 
-	if (bufdb == MyDatabaseId || bufdb == (Oid) NULL)
-		reln = RelationIdCacheGetRelation(bufrel);
-	else
-		reln = (Relation) NULL;
+	reln = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
 	/* To check if block content changed while flushing. - vadim 01/17/97 */
 	bufHdr->flags &= ~BM_JUST_DIRTIED;
@@ -1450,7 +1436,6 @@ BufferReplace(BufferDesc *bufHdr)
 
 	if (reln != (Relation) NULL)
 	{
-		Assert(RelFileNodeEquals(bufHdr->tag.rnode, reln->rd_node));
 		status = smgrwrite(DEFAULT_SMGR, reln, bufHdr->tag.blockNum,
 						   (char *) MAKE_PTR(bufHdr->data));
 	}
@@ -1519,7 +1504,6 @@ RelationGetNumberOfBlocks(Relation relation)
 void
 ReleaseRelationBuffers(Relation rel)
 {
-	Oid			relid = RelationGetRelid(rel);
 	int			i;
 	BufferDesc *bufHdr;
 
@@ -1534,10 +1518,6 @@ ReleaseRelationBuffers(Relation rel)
 				LocalRefCount[i] = 0;
 				bufHdr->tag.rnode.relNode = InvalidOid;
 			}
-			else
-			{
-				Assert(bufHdr->relId.relId != relid);
-			}
 		}
 		return;
 	}
@@ -1590,12 +1570,6 @@ recheck:
 			 */
 			BufTableDelete(bufHdr);
 		}
-		else
-		{
-			Assert(bufHdr->relId.relId != relid ||
-				   (bufHdr->relId.dbId != MyDatabaseId &&
-					bufHdr->relId.dbId != InvalidOid));
-		}
 
 		/*
 		 * Also check to see if BufferDirtiedByMe info for this buffer
@@ -1608,7 +1582,7 @@ recheck:
 		 * this rel, since we hold exclusive lock on this rel.
 		 */
 		if (RelFileNodeEquals(rel->rd_node, 
-							  BufferTagLastDirtied[i - 1].rnode))
+					  BufferTagLastDirtied[i - 1].rnode))
 			BufferDirtiedByMe[i - 1] = false;
 	}
 
@@ -1673,11 +1647,6 @@ recheck:
 			 */
 			BufTableDelete(bufHdr);
 		}
-		else
-		{
-			Assert(bufHdr->relId.dbId != dbid);
-		}
-
 		/*
 		 * Also check to see if BufferDirtiedByMe info for this buffer
 		 * refers to the target database, and clear it if so.  This is
@@ -1824,7 +1793,6 @@ BufferPoolBlowaway()
 int
 FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 {
-	Oid			relid = RelationGetRelid(rel);
 	int			i;
 	BufferDesc *bufHdr;
 
@@ -1857,10 +1825,6 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 					bufHdr->tag.rnode.relNode = InvalidOid;
 				}
 			}
-			else
-			{
-				Assert(bufHdr->relId.relId != relid);
-			}
 		}
 		return 0;
 	}
@@ -1906,12 +1870,6 @@ recheck:
 				BufTableDelete(bufHdr);
 			}
 		}
-		else
-		{
-			Assert(bufHdr->relId.relId != relid ||
-				(bufHdr->relId.dbId != MyDatabaseId &&
-				bufHdr->relId.dbId != InvalidOid));
-		}
 	}
 	SpinRelease(BufMgrLock);
 	return 0;
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 3cb8f572b896bbf4352c0d007f91fcd434d4e347..1d6a416e48e2c95aa2cd9c2512de7dc540dce717 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.31 2000/10/18 05:50:15 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.32 2000/10/23 04:10:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -103,7 +103,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 	 */
 	if (bufHdr->flags & BM_DIRTY)
 	{
-		Relation	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
+		Relation	bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
 		Assert(bufrel != NULL);
 
@@ -127,7 +127,6 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 	 */
 	bufHdr->tag.rnode = reln->rd_node;
 	bufHdr->tag.blockNum = blockNum;
-	bufHdr->relId = reln->rd_lockInfo.lockRelId;
 	bufHdr->flags &= ~BM_DIRTY;
 
 	/*
@@ -192,7 +191,7 @@ FlushLocalBuffer(Buffer buffer, bool release)
 	bufid = -(buffer + 1);
 	bufHdr = &LocalBufferDescriptors[bufid];
 	bufHdr->flags &= ~BM_DIRTY;
-	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
+	bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
 
 	Assert(bufrel != NULL);
 	smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
@@ -268,7 +267,7 @@ LocalBufferSync(void)
 #ifdef LBDEBUG
 			fprintf(stderr, "LB SYNC %d\n", -i - 1);
 #endif
-			bufrel = RelationIdCacheGetRelation(buf->relId.relId);
+			bufrel = RelationNodeCacheGetRelation(buf->tag.rnode);
 
 			Assert(bufrel != NULL);
 
@@ -279,7 +278,6 @@ LocalBufferSync(void)
 			/* drop relcache refcount from RelationIdCacheGetRelation */
 			RelationDecrementReferenceCount(bufrel);
 
-			buf->relId.relId = InvalidOid;
 			buf->flags &= ~BM_DIRTY;
 		}
 	}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 755359e2514a4333b15c26a7ed6f84e6843b140b..de3e3c4a8d30d2ae20443168169e3ce7a3255dfe 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.112 2000/10/16 14:52:13 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.113 2000/10/23 04:10:08 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,6 +83,13 @@ static FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log};
 static HTAB *RelationNameCache;
 static HTAB *RelationIdCache;
 
+/*
+ * Bufmgr uses RelFileNode for lookup. Actually, I would like to do
+ * not pass Relation to bufmgr & beyond at all and keep some cache
+ * in smgr, but no time to do it right way now.		-- vadim 10/22/2000
+ */
+static HTAB *RelationNodeCache;
+
 /*
  * newlyCreatedRelns -
  *	  relations created during this transaction. We need to keep track of
@@ -114,17 +121,23 @@ typedef struct RelationBuildDescInfo
 	}			i;
 } RelationBuildDescInfo;
 
+typedef struct relnamecacheent
+{
+	NameData	relname;
+	Relation	reldesc;
+} RelNameCacheEnt;
+
 typedef struct relidcacheent
 {
 	Oid			reloid;
 	Relation	reldesc;
 } RelIdCacheEnt;
 
-typedef struct relnamecacheent
+typedef struct relnodecacheent
 {
-	NameData	relname;
+	RelFileNode	relnode;
 	Relation	reldesc;
-} RelNameCacheEnt;
+} RelNodeCacheEnt;
 
 /* -----------------
  *		macros to manipulate name cache and id cache
@@ -133,7 +146,7 @@ typedef struct relnamecacheent
 #define RelationCacheInsert(RELATION)	\
 do { \
 	RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \
-	char *relname; Oid reloid; bool found; \
+	char *relname; RelNodeCacheEnt *nodentry; bool found; \
 	relname = RelationGetPhysicalRelationName(RELATION); \
 	namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
 											   relname, \
@@ -144,9 +157,8 @@ do { \
 	if (found && !IsBootstrapProcessingMode()) \
 		/* used to give notice -- now just keep quiet */ ; \
 	namehentry->reldesc = RELATION; \
-	reloid = RELATION->rd_id; \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										   (char *)&reloid, \
+										   (char *)&(RELATION->rd_id), \
 										   HASH_ENTER, \
 										   &found); \
 	if (idhentry == NULL) \
@@ -154,6 +166,15 @@ do { \
 	if (found && !IsBootstrapProcessingMode()) \
 		/* used to give notice -- now just keep quiet */ ; \
 	idhentry->reldesc = RELATION; \
+	nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
+										   (char *)&(RELATION->rd_node), \
+										   HASH_ENTER, \
+										   &found); \
+	if (nodentry == NULL) \
+		elog(FATAL, "can't insert into relation descriptor cache"); \
+	if (found && !IsBootstrapProcessingMode()) \
+		/* used to give notice -- now just keep quiet */ ; \
+	nodentry->reldesc = RELATION; \
 } while(0)
 
 #define RelationNameCacheLookup(NAME, RELATION) \
@@ -183,10 +204,24 @@ do { \
 		RELATION = NULL; \
 } while(0)
 
+#define RelationNodeCacheLookup(NODE, RELATION) \
+do { \
+	RelNodeCacheEnt *hentry; \
+	bool found; \
+	hentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
+									 (char *)&(NODE),HASH_FIND, &found); \
+	if (hentry == NULL) \
+		elog(FATAL, "error in CACHE"); \
+	if (found) \
+		RELATION = hentry->reldesc; \
+	else \
+		RELATION = NULL; \
+} while(0)
+
 #define RelationCacheDelete(RELATION) \
 do { \
 	RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \
-	char *relname; Oid reloid; bool found; \
+	char *relname; RelNodeCacheEnt *nodentry; bool found; \
 	relname = RelationGetPhysicalRelationName(RELATION); \
 	namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
 											   relname, \
@@ -196,14 +231,20 @@ do { \
 		elog(FATAL, "can't delete from relation descriptor cache"); \
 	if (!found) \
 		elog(NOTICE, "trying to delete a reldesc that does not exist."); \
-	reloid = RELATION->rd_id; \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										   (char *)&reloid, \
+										   (char *)&(RELATION->rd_id), \
 										   HASH_REMOVE, &found); \
 	if (idhentry == NULL) \
 		elog(FATAL, "can't delete from relation descriptor cache"); \
 	if (!found) \
 		elog(NOTICE, "trying to delete a reldesc that does not exist."); \
+	nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
+										   (char *)&(RELATION->rd_node), \
+										   HASH_REMOVE, &found); \
+	if (nodentry == NULL) \
+		elog(FATAL, "can't delete from relation descriptor cache"); \
+	if (!found) \
+		elog(NOTICE, "trying to delete a reldesc that does not exist."); \
 } while(0)
 
 /* non-export function prototypes */
@@ -1192,12 +1233,6 @@ formrdesc(char *relationName,
 	 */
 	RelationInitLockInfo(relation);		/* see lmgr.c */
 
-	/* ----------------
-	 *	add new reldesc to relcache
-	 * ----------------
-	 */
-	RelationCacheInsert(relation);
-
 	if (IsSharedSystemRelationName(relationName))
 		relation->rd_node.tblNode = InvalidOid;
 	else
@@ -1205,6 +1240,12 @@ formrdesc(char *relationName,
 	relation->rd_node.relNode = 
 		relation->rd_rel->relfilenode = RelationGetRelid(relation);
 
+	/* ----------------
+	 *	add new reldesc to relcache
+	 * ----------------
+	 */
+	RelationCacheInsert(relation);
+
 	/*
 	 * Determining this requires a scan on pg_class, but to do the scan
 	 * the rdesc for pg_class must already exist.  Therefore we must do
@@ -1343,6 +1384,28 @@ RelationNameCacheGetRelation(const char *relationName)
 	return rd;
 }
 
+Relation
+RelationNodeCacheGetRelation(RelFileNode rnode)
+{
+	Relation	rd;
+
+	RelationNodeCacheLookup(rnode, rd);
+
+	if (RelationIsValid(rd))
+	{
+		if (rd->rd_fd == -1 && rd->rd_rel->relkind != RELKIND_VIEW)
+		{
+			rd->rd_fd = smgropen(DEFAULT_SMGR, rd);
+			Assert(rd->rd_fd != -1 || rd->rd_unlinked);
+		}
+
+		RelationIncrementReferenceCount(rd);
+
+	}
+
+	return rd;
+}
+
 /* --------------------------------
  *		RelationIdGetRelation
  *
@@ -1942,6 +2005,11 @@ RelationCacheInitialize(void)
 	RelationIdCache = hash_create(INITRELCACHESIZE, &ctl,
 								  HASH_ELEM | HASH_FUNCTION);
 
+	ctl.keysize = sizeof(RelFileNode);
+	ctl.hash = tag_hash;
+	RelationNodeCache = hash_create(INITRELCACHESIZE, &ctl,
+								  HASH_ELEM | HASH_FUNCTION);
+
 	/* ----------------
 	 *	initialize the cache with pre-made relation descriptors
 	 *	for some of the more important system relations.  These
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 86512e50bf81bfd85c25ae581b3f318edab75ec1..65abe9b8ceb5a1502f1d64225d65ddcb54d48a07 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.40 2000/10/20 11:01:21 vadim Exp $
+ * $Id: buf_internals.h,v 1.41 2000/10/23 04:10:14 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,22 +109,6 @@ typedef struct sbufdesc
 	bool		ri_lock;		/* read-intent lock */
 	bool		w_lock;			/* context exclusively locked */
 
-	/* 
-	 * This is logical information about relation.
-	 * IT MUST CORRESPOND TO BUFFER TAG!
-	 * If you're going to play with relation file node (ie change relation
-	 * file) then you have to exclusively lock relation, create new one
-	 * (with new relID), make data transformation, flush from pool buffers
-	 * of both files (old and new), flush old relation from cache,
-	 * update relfilenode in pg_class, flush new relation version from
-	 * cache, open it - now you can use relation with new file.
-	 *
-	 * Why we keep relId here? To re-use file descriptors. On rollback
-	 * WAL uses dummy relId - bad (more blind writes - open/close calls),
-	 * but allowable. Obviously we should have another cache in file manager
-	 * - fd is not relcache deal.
-	 */
-	LockRelId	relId;
 	BufferBlindId blind;		/* was used to support blind write */
 
 	/*
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index a2a2b5eb777ada97c7731797149fa5c08e48dfa7..fc15ed5b19c037beadbbb263060a2178f0d30079 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relcache.h,v 1.21 2000/08/06 04:39:55 tgl Exp $
+ * $Id: relcache.h,v 1.22 2000/10/23 04:10:24 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
  */
 extern Relation RelationIdGetRelation(Oid relationId);
 extern Relation RelationNameGetRelation(const char *relationName);
+extern Relation RelationNodeCacheGetRelation(RelFileNode rnode);
 
 /* finds an existing cache entry, but won't make a new one */
 extern Relation RelationIdCacheGetRelation(Oid relationId);