*
*
* 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:
*/
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.
if (leak)
ResetBufferPool(true);
+#endif
/*
* have the transaction access methods record the status of this
* transaction id in the pg_log relation.
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
nextRecord = (XLogRecord *) ((char *) subrecord +
MAXALIGN(subrecord->xl_len) + SizeOfXLogSubRecord);
}
+ record->xl_len = len;
EndRecPtr.xlogid = readId;
EndRecPtr.xrecoff = readSeg * XLogSegSize + readOff * BLCKSZ +
SizeOfXLogPHD + SizeOfXLogSubRecord +
{
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
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));
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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;
/* 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))
FlushBuffer(Buffer buffer, bool release)
{
BufferDesc *bufHdr;
- Oid bufdb;
Relation bufrel;
int status;
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);
SpinRelease(BufMgrLock);
#endif /* OPTIMIZE_SINGLE */
- reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[buffer - 1].relId);
+ reln = RelationNodeCacheGetRelation(tagLastDirtied->rnode);
if (reln == (Relation) NULL)
{
}
*tagLastDirtied = bufHdr->tag;
- BufferRelidLastDirtied[buffer - 1] = bufHdr->relId;
BufferBlindLastDirtied[buffer - 1] = bufHdr->blind;
BufferDirtiedByMe[buffer - 1] = true;
}
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
}
else
{
- Assert(RelFileNodeEquals(reln->rd_node,
- BufferTagLastDirtied[i].rnode));
status = smgrwrite(DEFAULT_SMGR, reln,
bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
SpinRelease(BufMgrLock);
#endif /* OPTIMIZE_SINGLE */
- reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[i].relId);
+ reln = RelationNodeCacheGetRelation(BufferTagLastDirtied[i].rnode);
if (reln == (Relation) NULL)
{
status = smgrblindmarkdirty(DEFAULT_SMGR,
}
else
{
- Assert(RelFileNodeEquals(reln->rd_node,
- BufferTagLastDirtied[i].rnode));
status = smgrmarkdirty(DEFAULT_SMGR, reln,
BufferTagLastDirtied[i].blockNum);
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;
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));
}
void
ReleaseRelationBuffers(Relation rel)
{
- Oid relid = RelationGetRelid(rel);
int i;
BufferDesc *bufHdr;
LocalRefCount[i] = 0;
bufHdr->tag.rnode.relNode = InvalidOid;
}
- else
- {
- Assert(bufHdr->relId.relId != relid);
- }
}
return;
}
*/
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
* 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;
}
*/
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
int
FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
{
- Oid relid = RelationGetRelid(rel);
int i;
BufferDesc *bufHdr;
bufHdr->tag.rnode.relNode = InvalidOid;
}
}
- else
- {
- Assert(bufHdr->relId.relId != relid);
- }
}
return 0;
}
BufTableDelete(bufHdr);
}
}
- else
- {
- Assert(bufHdr->relId.relId != relid ||
- (bufHdr->relId.dbId != MyDatabaseId &&
- bufHdr->relId.dbId != InvalidOid));
- }
}
SpinRelease(BufMgrLock);
return 0;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
if (bufHdr->flags & BM_DIRTY)
{
- Relation bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
+ Relation bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
Assert(bufrel != NULL);
*/
bufHdr->tag.rnode = reln->rd_node;
bufHdr->tag.blockNum = blockNum;
- bufHdr->relId = reln->rd_lockInfo.lockRelId;
bufHdr->flags &= ~BM_DIRTY;
/*
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,
#ifdef LBDEBUG
fprintf(stderr, "LB SYNC %d\n", -i - 1);
#endif
- bufrel = RelationIdCacheGetRelation(buf->relId.relId);
+ bufrel = RelationNodeCacheGetRelation(buf->tag.rnode);
Assert(bufrel != NULL);
/* drop relcache refcount from RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
- buf->relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
} 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
#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, \
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) \
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) \
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, \
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 */
*/
RelationInitLockInfo(relation); /* see lmgr.c */
- /* ----------------
- * add new reldesc to relcache
- * ----------------
- */
- RelationCacheInsert(relation);
-
if (IsSharedSystemRelationName(relationName))
relation->rd_node.tblNode = InvalidOid;
else
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
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
*
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
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
/*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
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);