aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/buffer/buf_init.c8
-rw-r--r--src/backend/storage/buffer/buf_table.c6
-rw-r--r--src/backend/storage/buffer/bufmgr.c313
-rw-r--r--src/backend/storage/buffer/localbuf.c21
-rw-r--r--src/include/storage/buf_internals.h47
-rw-r--r--src/include/storage/relfilenode.h4
6 files changed, 156 insertions, 243 deletions
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 5023b404261..13aca31a3e4 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.35 2000/05/31 00:28:26 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.36 2000/10/18 05:50:15 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,8 +67,9 @@ long *PrivateRefCount; /* also used in freelist.c */
bits8 *BufferLocks; /* flag bits showing locks I have set */
BufferTag *BufferTagLastDirtied; /* tag buffer had when last
* dirtied by me */
-BufferBlindId *BufferBlindLastDirtied; /* and its BlindId too */
-bool *BufferDirtiedByMe; /* T if buf has been dirtied in cur xact */
+BufferBlindId *BufferBlindLastDirtied;
+LockRelId *BufferRelidLastDirtied;
+bool *BufferDirtiedByMe; /* T if buf has been dirtied in cur xact */
/*
@@ -251,6 +252,7 @@ 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/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 8139337e352..d48d321e8f8 100644
--- a/src/backend/storage/buffer/buf_table.c
+++ b/src/backend/storage/buffer/buf_table.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.17 2000/05/19 03:22:28 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.18 2000/10/18 05:50:15 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -125,8 +125,8 @@ BufTableDelete(BufferDesc *buf)
* sequential searches through the buffer table won't think the
* buffer is still valid for its old page.
*/
- buf->tag.relId.relId = InvalidOid;
- buf->tag.relId.dbId = InvalidOid;
+ buf->tag.rnode.relNode = InvalidOid;
+ buf->tag.rnode.tblNode = InvalidOid;
return TRUE;
}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index d5badefd084..41ee78e547c 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.86 2000/10/16 14:52:09 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.87 2000/10/18 05:50:15 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -116,13 +116,10 @@ RelationGetBufferWithBuffer(Relation relation,
{
if (!BufferIsLocal(buffer))
{
- LockRelId *lrelId = &relation->rd_lockInfo.lockRelId;
-
bufHdr = &BufferDescriptors[buffer - 1];
SpinAcquire(BufMgrLock);
if (bufHdr->tag.blockNum == blockNumber &&
- bufHdr->tag.relId.relId == lrelId->relId &&
- bufHdr->tag.relId.dbId == lrelId->dbId)
+ RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
{
SpinRelease(BufMgrLock);
return buffer;
@@ -132,8 +129,8 @@ RelationGetBufferWithBuffer(Relation relation,
else
{
bufHdr = &LocalBufferDescriptors[-buffer - 1];
- if (bufHdr->tag.relId.relId == RelationGetRelid(relation) &&
- bufHdr->tag.blockNum == blockNumber)
+ if (bufHdr->tag.blockNum == blockNumber &&
+ RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
return buffer;
}
}
@@ -614,9 +611,7 @@ BufferAlloc(Relation reln,
/* record the database name and relation name for this buffer */
strcpy(buf->blind.dbname, DatabaseName);
strcpy(buf->blind.relname, RelationGetPhysicalRelationName(reln));
-#ifndef OLD_FILE_NAMING
- buf->blind.rnode = reln->rd_node;
-#endif
+ buf->relId = reln->rd_lockInfo.lockRelId;
INIT_BUFFERTAG(&(buf->tag), reln, blockNum);
if (!BufTableInsert(buf))
@@ -704,59 +699,6 @@ refcount = %ld, file: %s, line: %d\n",
#endif
/*
- * DirtyBufferCopy() -- For a given dbid/relid/blockno, if the buffer is
- * in the cache and is dirty, mark it clean and copy
- * it to the requested location. This is a logical
- * write, and has been installed to support the cache
- * management code for write-once storage managers.
- *
- * DirtyBufferCopy() -- Copy a given dirty buffer to the requested
- * destination.
- *
- * We treat this as a write. If the requested buffer is in the pool
- * and is dirty, we copy it to the location requested and mark it
- * clean. This routine supports the Sony jukebox storage manager,
- * which agrees to take responsibility for the data once we mark
- * it clean.
- *
- * NOTE: used by sony jukebox code in postgres 4.2 - ay 2/95
- */
-#ifdef NOT_USED
-void
-DirtyBufferCopy(Oid dbid, Oid relid, BlockNumber blkno, char *dest)
-{
- BufferDesc *buf;
- BufferTag btag;
-
- btag.relId.relId = relid;
- btag.relId.dbId = dbid;
- btag.blockNum = blkno;
-
- SpinAcquire(BufMgrLock);
- buf = BufTableLookup(&btag);
-
- if (buf == (BufferDesc *) NULL
- || !(buf->flags & BM_DIRTY)
- || !(buf->flags & BM_VALID))
- {
- SpinRelease(BufMgrLock);
- return;
- }
-
- /*
- * hate to do this holding the lock, but release and reacquire is
- * slower
- */
- memmove(dest, (char *) MAKE_PTR(buf->data), BLCKSZ);
-
- buf->flags &= ~BM_DIRTY;
-
- SpinRelease(BufMgrLock);
-}
-
-#endif
-
-/*
* FlushBuffer -- like WriteBuffer, but force the page to disk.
*
* 'buffer' is known to be dirty/pinned, so there should not be a
@@ -783,10 +725,10 @@ FlushBuffer(Buffer buffer, bool release)
bufHdr = &BufferDescriptors[buffer - 1];
- bufdb = bufHdr->tag.relId.dbId;
+ bufdb = bufHdr->relId.dbId;
Assert(bufdb == MyDatabaseId || bufdb == (Oid) NULL);
- bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+ bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
Assert(bufrel != (Relation) NULL);
@@ -954,8 +896,7 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
*/
if (BufferDirtiedByMe[buffer - 1])
{
- if (bufHdr->tag.relId.dbId == tagLastDirtied->relId.dbId &&
- bufHdr->tag.relId.relId == tagLastDirtied->relId.relId &&
+ if (RelFileNodeEquals(bufHdr->tag.rnode, tagLastDirtied->rnode) &&
bufHdr->tag.blockNum == tagLastDirtied->blockNum)
return; /* Same tag already dirtied, so no work */
@@ -963,25 +904,17 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
SpinRelease(BufMgrLock);
#endif /* OPTIMIZE_SINGLE */
- reln = RelationIdCacheGetRelation(tagLastDirtied->relId.relId);
+ reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[buffer - 1].relId);
if (reln == (Relation) NULL)
{
-#ifdef OLD_FILE_NAMING
- status = smgrblindmarkdirty(DEFAULT_SMGR,
- BufferBlindLastDirtied[buffer - 1].dbname,
- BufferBlindLastDirtied[buffer - 1].relname,
- tagLastDirtied->relId.dbId,
- tagLastDirtied->relId.relId,
- tagLastDirtied->blockNum);
-#else
status = smgrblindmarkdirty(DEFAULT_SMGR,
- BufferBlindLastDirtied[buffer - 1].rnode,
+ tagLastDirtied->rnode,
tagLastDirtied->blockNum);
-#endif
}
else
{
+ Assert(RelFileNodeEquals(tagLastDirtied->rnode, reln->rd_node));
status = smgrmarkdirty(DEFAULT_SMGR, reln,
tagLastDirtied->blockNum);
@@ -1005,6 +938,7 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
}
*tagLastDirtied = bufHdr->tag;
+ BufferRelidLastDirtied[buffer - 1] = bufHdr->relId;
BufferBlindLastDirtied[buffer - 1] = bufHdr->blind;
BufferDirtiedByMe[buffer - 1] = true;
}
@@ -1028,10 +962,9 @@ ClearBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
* the data we just wrote. This is unlikely, but possible if some
* other backend replaced the buffer contents since we set our flag.
*/
- if (bufHdr->tag.relId.dbId == tagLastDirtied->relId.dbId &&
- bufHdr->tag.relId.relId == tagLastDirtied->relId.relId &&
- bufHdr->tag.blockNum == tagLastDirtied->blockNum)
- BufferDirtiedByMe[buffer - 1] = false;
+ if (RelFileNodeEquals(bufHdr->tag.rnode, tagLastDirtied->rnode) &&
+ bufHdr->tag.blockNum == tagLastDirtied->blockNum)
+ BufferDirtiedByMe[buffer - 1] = false;
}
/*
@@ -1074,15 +1007,10 @@ BufferSync()
didwrite = false;
if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
{
- Oid bufdb;
- Oid bufrel;
-
- bufdb = bufHdr->tag.relId.dbId;
- bufrel = bufHdr->tag.relId.relId;
- if (bufdb == BufferTagLastDirtied[i].relId.dbId &&
- bufrel == BufferTagLastDirtied[i].relId.relId &&
+ 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
@@ -1147,24 +1075,16 @@ BufferSync()
*/
if (reln == (Relation) NULL)
{
-#ifdef OLD_FILE_NAMING
- status = smgrblindwrt(DEFAULT_SMGR,
- bufHdr->blind.dbname,
- bufHdr->blind.relname,
- bufdb, bufrel,
- bufHdr->tag.blockNum,
- (char *) MAKE_PTR(bufHdr->data),
- true); /* must fsync */
-#else
status = smgrblindwrt(DEFAULT_SMGR,
- bufHdr->blind.rnode,
+ bufHdr->tag.rnode,
bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data),
true); /* must fsync */
-#endif
}
else
{
+ Assert(RelFileNodeEquals(reln->rd_node,
+ BufferTagLastDirtied[i].rnode));
status = smgrwrite(DEFAULT_SMGR, reln,
bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
@@ -1218,24 +1138,17 @@ BufferSync()
SpinRelease(BufMgrLock);
#endif /* OPTIMIZE_SINGLE */
- reln = RelationIdCacheGetRelation(BufferTagLastDirtied[i].relId.relId);
+ reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[i].relId);
if (reln == (Relation) NULL)
{
-#ifdef OLD_FILE_NAMING
- status = smgrblindmarkdirty(DEFAULT_SMGR,
- BufferBlindLastDirtied[i].dbname,
- BufferBlindLastDirtied[i].relname,
- BufferTagLastDirtied[i].relId.dbId,
- BufferTagLastDirtied[i].relId.relId,
- BufferTagLastDirtied[i].blockNum);
-#else
status = smgrblindmarkdirty(DEFAULT_SMGR,
- BufferBlindLastDirtied[i].rnode,
+ BufferTagLastDirtied[i].rnode,
BufferTagLastDirtied[i].blockNum);
-#endif
}
else
{
+ Assert(RelFileNodeEquals(reln->rd_node,
+ BufferTagLastDirtied[i].rnode));
status = smgrmarkdirty(DEFAULT_SMGR, reln,
BufferTagLastDirtied[i].blockNum);
@@ -1492,46 +1405,6 @@ BufferGetBlockNumber(Buffer buffer)
return BufferDescriptors[buffer - 1].tag.blockNum;
}
-#ifdef NOT_USED
-/*
- * BufferGetRelation
- * Returns the relation desciptor associated with a buffer.
- *
- * Note:
- * Assumes buffer is valid.
- */
-Relation
-BufferGetRelation(Buffer buffer)
-{
- Relation relation;
- Oid relid;
-
- Assert(BufferIsValid(buffer));
- Assert(!BufferIsLocal(buffer)); /* not supported for local buffers */
-
- /* XXX should be a critical section */
- relid = BufferDescriptors[buffer - 1].tag.relId.relId;
- relation = RelationIdGetRelation(relid);
- Assert(relation);
-
- /* drop relcache refcnt incremented by RelationIdGetRelation */
- RelationDecrementReferenceCount(relation);
-
- if (RelationHasReferenceCountZero(relation))
- {
-
- /*
- * XXX why??
- */
-
- RelationIncrementReferenceCount(relation);
- }
-
- return relation;
-}
-
-#endif
-
/*
* BufferReplace
*
@@ -1554,8 +1427,8 @@ BufferReplace(BufferDesc *bufHdr)
* 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->tag.relId.dbId;
- bufrel = bufHdr->tag.relId.relId;
+ bufdb = bufHdr->relId.dbId;
+ bufrel = bufHdr->relId.relId;
if (bufdb == MyDatabaseId || bufdb == (Oid) NULL)
reln = RelationIdCacheGetRelation(bufrel);
@@ -1576,23 +1449,16 @@ 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));
}
else
{
-#ifdef OLD_FILE_NAMING
- status = smgrblindwrt(DEFAULT_SMGR, bufHdr->blind.dbname,
- bufHdr->blind.relname, bufdb, bufrel,
+ status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode,
bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data),
false); /* no fsync */
-#else
- status = smgrblindwrt(DEFAULT_SMGR, bufHdr->blind.rnode,
- bufHdr->tag.blockNum,
- (char *) MAKE_PTR(bufHdr->data),
- false); /* no fsync */
-#endif
}
LockBuffer(BufferDescriptorGetBuffer(bufHdr), BUFFER_LOCK_UNLOCK);
@@ -1654,18 +1520,22 @@ ReleaseRelationBuffers(Relation rel)
{
Oid relid = RelationGetRelid(rel);
int i;
- BufferDesc *buf;
+ BufferDesc *bufHdr;
if (rel->rd_myxactonly)
{
for (i = 0; i < NLocBuffer; i++)
{
- buf = &LocalBufferDescriptors[i];
- if (buf->tag.relId.relId == relid)
+ bufHdr = &LocalBufferDescriptors[i];
+ if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
- buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+ bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
LocalRefCount[i] = 0;
- buf->tag.relId.relId = InvalidOid;
+ bufHdr->tag.rnode.relNode = InvalidOid;
+ }
+ else
+ {
+ Assert(bufHdr->relId.relId != relid);
}
}
return;
@@ -1674,11 +1544,9 @@ ReleaseRelationBuffers(Relation rel)
SpinAcquire(BufMgrLock);
for (i = 1; i <= NBuffers; i++)
{
- buf = &BufferDescriptors[i - 1];
+ bufHdr = &BufferDescriptors[i - 1];
recheck:
- if (buf->tag.relId.relId == relid &&
- (buf->tag.relId.dbId == MyDatabaseId ||
- buf->tag.relId.dbId == (Oid) NULL))
+ if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
/*
@@ -1686,9 +1554,9 @@ recheck:
* don't want to delete the relation out from under someone
* who's just trying to flush the buffer!
*/
- if (buf->flags & BM_IO_IN_PROGRESS)
+ if (bufHdr->flags & BM_IO_IN_PROGRESS)
{
- WaitIO(buf, BufMgrLock);
+ WaitIO(bufHdr, BufMgrLock);
/*
* By now, the buffer very possibly belongs to some other
@@ -1697,8 +1565,8 @@ recheck:
goto recheck;
}
/* Now we can do what we came for */
- buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
- ClearBufferDirtiedByMe(i, buf);
+ bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+ BufferDirtiedByMe[i - 1] = false;
/*
* Release any refcount we may have.
@@ -1707,11 +1575,11 @@ recheck:
* probably wrong. I added the Assert to find out --- tgl
* 11/99.
*/
- if (!(buf->flags & BM_FREE))
+ if (!(bufHdr->flags & BM_FREE))
{
/* Assert checks that buffer will actually get freed! */
Assert(PrivateRefCount[i - 1] == 1 &&
- buf->refcount == 1);
+ bufHdr->refcount == 1);
/* ReleaseBuffer expects we do not hold the lock at entry */
SpinRelease(BufMgrLock);
ReleaseBuffer(i);
@@ -1720,9 +1588,19 @@ recheck:
/*
* And mark the buffer as no longer occupied by this rel.
*/
- BufTableDelete(buf);
+ BufTableDelete(bufHdr);
+ }
+ else
+ {
+ Assert(bufHdr->relId.relId != relid ||
+ (bufHdr->relId.dbId != MyDatabaseId &&
+ bufHdr->relId.dbId != InvalidOid));
+ if (RelFileNodeEquals(rel->rd_node,
+ BufferTagLastDirtied[i - 1].rnode))
+ BufferDirtiedByMe[i - 1] = false;
}
}
+
SpinRelease(BufMgrLock);
}
@@ -1741,14 +1619,19 @@ void
DropBuffers(Oid dbid)
{
int i;
- BufferDesc *buf;
+ BufferDesc *bufHdr;
SpinAcquire(BufMgrLock);
for (i = 1; i <= NBuffers; i++)
{
- buf = &BufferDescriptors[i - 1];
+ bufHdr = &BufferDescriptors[i - 1];
recheck:
- if (buf->tag.relId.dbId == dbid)
+ /*
+ * We know that currently database OID is tblNode but
+ * this probably will be changed in future and this
+ * func will be used to drop tablespace buffers.
+ */
+ if (bufHdr->tag.rnode.tblNode == dbid)
{
/*
@@ -1756,9 +1639,9 @@ recheck:
* don't want to delete the database out from under someone
* who's just trying to flush the buffer!
*/
- if (buf->flags & BM_IO_IN_PROGRESS)
+ if (bufHdr->flags & BM_IO_IN_PROGRESS)
{
- WaitIO(buf, BufMgrLock);
+ WaitIO(bufHdr, BufMgrLock);
/*
* By now, the buffer very possibly belongs to some other
@@ -1767,18 +1650,24 @@ recheck:
goto recheck;
}
/* Now we can do what we came for */
- buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
- ClearBufferDirtiedByMe(i, buf);
+ bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+ BufferDirtiedByMe[i - 1] = false;
/*
* The thing should be free, if caller has checked that no
* backends are running in that database.
*/
- Assert(buf->flags & BM_FREE);
+ Assert(bufHdr->flags & BM_FREE);
/*
* And mark the buffer as no longer occupied by this page.
*/
- BufTableDelete(buf);
+ BufTableDelete(bufHdr);
+ }
+ else
+ {
+ Assert(bufHdr->relId.dbId != dbid);
+ if (BufferTagLastDirtied[i - 1].rnode.tblNode == dbid)
+ BufferDirtiedByMe[i - 1] = false;
}
}
SpinRelease(BufMgrLock);
@@ -1917,22 +1806,22 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
{
Oid relid = RelationGetRelid(rel);
int i;
- BufferDesc *buf;
+ BufferDesc *bufHdr;
if (rel->rd_myxactonly)
{
for (i = 0; i < NLocBuffer; i++)
{
- buf = &LocalBufferDescriptors[i];
- if (buf->tag.relId.relId == relid)
+ bufHdr = &LocalBufferDescriptors[i];
+ if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
- if (buf->flags & BM_DIRTY)
+ if (bufHdr->flags & BM_DIRTY)
{
if (FlushBuffer(-i - 1, false) != STATUS_OK)
{
elog(NOTICE, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
RelationGetRelationName(rel), firstDelBlock,
- buf->tag.blockNum);
+ bufHdr->tag.blockNum);
return -1;
}
}
@@ -1940,14 +1829,18 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
{
elog(NOTICE, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
RelationGetRelationName(rel), firstDelBlock,
- buf->tag.blockNum, LocalRefCount[i]);
+ bufHdr->tag.blockNum, LocalRefCount[i]);
return -2;
}
- if (buf->tag.blockNum >= firstDelBlock)
+ if (bufHdr->tag.blockNum >= firstDelBlock)
{
- buf->tag.relId.relId = InvalidOid;
+ bufHdr->tag.rnode.relNode = InvalidOid;
}
}
+ else
+ {
+ Assert(bufHdr->relId.relId != relid);
+ }
}
return 0;
}
@@ -1955,22 +1848,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
SpinAcquire(BufMgrLock);
for (i = 0; i < NBuffers; i++)
{
- buf = &BufferDescriptors[i];
+ bufHdr = &BufferDescriptors[i];
recheck:
- if (buf->tag.relId.relId == relid &&
- (buf->tag.relId.dbId == MyDatabaseId ||
- buf->tag.relId.dbId == (Oid) NULL))
+ if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
- if (buf->flags & BM_DIRTY)
+ if (bufHdr->flags & BM_DIRTY)
{
- PinBuffer(buf);
+ PinBuffer(bufHdr);
SpinRelease(BufMgrLock);
if (FlushBuffer(i + 1, true) != STATUS_OK)
{
elog(NOTICE, "FlushRelationBuffers(%s, %u): block %u is dirty (private %ld, global %d), could not flush it",
RelationGetRelationName(rel), firstDelBlock,
- buf->tag.blockNum,
- PrivateRefCount[i], buf->refcount);
+ bufHdr->tag.blockNum,
+ PrivateRefCount[i], bufHdr->refcount);
return -1;
}
SpinAcquire(BufMgrLock);
@@ -1981,20 +1872,26 @@ recheck:
*/
goto recheck;
}
- if (!(buf->flags & BM_FREE))
+ if (!(bufHdr->flags & BM_FREE))
{
SpinRelease(BufMgrLock);
elog(NOTICE, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
RelationGetRelationName(rel), firstDelBlock,
- buf->tag.blockNum,
- PrivateRefCount[i], buf->refcount);
+ bufHdr->tag.blockNum,
+ PrivateRefCount[i], bufHdr->refcount);
return -2;
}
- if (buf->tag.blockNum >= firstDelBlock)
+ if (bufHdr->tag.blockNum >= firstDelBlock)
{
- BufTableDelete(buf);
+ 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 91eff97f264..3cb8f572b89 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.30 2000/04/12 17:15:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.31 2000/10/18 05:50:15 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -60,7 +60,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
/* a low tech search for now -- not optimized for scans */
for (i = 0; i < NLocBuffer; i++)
{
- if (LocalBufferDescriptors[i].tag.relId.relId == RelationGetRelid(reln) &&
+ if (LocalBufferDescriptors[i].tag.rnode.relNode ==
+ reln->rd_node.relNode &&
LocalBufferDescriptors[i].tag.blockNum == blockNum)
{
@@ -102,7 +103,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
*/
if (bufHdr->flags & BM_DIRTY)
{
- Relation bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+ Relation bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
Assert(bufrel != NULL);
@@ -120,9 +121,13 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
/*
* 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.relId.relId = RelationGetRelid(reln);
+ bufHdr->tag.rnode = reln->rd_node;
bufHdr->tag.blockNum = blockNum;
+ bufHdr->relId = reln->rd_lockInfo.lockRelId;
bufHdr->flags &= ~BM_DIRTY;
/*
@@ -187,7 +192,7 @@ FlushLocalBuffer(Buffer buffer, bool release)
bufid = -(buffer + 1);
bufHdr = &LocalBufferDescriptors[bufid];
bufHdr->flags &= ~BM_DIRTY;
- bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+ bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
Assert(bufrel != NULL);
smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
@@ -263,7 +268,7 @@ LocalBufferSync(void)
#ifdef LBDEBUG
fprintf(stderr, "LB SYNC %d\n", -i - 1);
#endif
- bufrel = RelationIdCacheGetRelation(buf->tag.relId.relId);
+ bufrel = RelationIdCacheGetRelation(buf->relId.relId);
Assert(bufrel != NULL);
@@ -274,7 +279,7 @@ LocalBufferSync(void)
/* drop relcache refcount from RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
- buf->tag.relId.relId = InvalidOid;
+ buf->relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
}
}
@@ -292,7 +297,7 @@ ResetLocalBufferPool(void)
{
BufferDesc *buf = &LocalBufferDescriptors[i];
- buf->tag.relId.relId = InvalidOid;
+ buf->tag.rnode.relNode = InvalidOid;
buf->flags &= ~BM_DIRTY;
buf->buf_id = -i - 2;
}
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 4f4a516afdf..12bf6604da1 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.38 2000/10/16 14:52:28 vadim Exp $
+ * $Id: buf_internals.h,v 1.39 2000/10/18 05:50:16 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,27 +44,27 @@ typedef long **BufferBlock;
typedef struct buftag
{
- LockRelId relId;
+ RelFileNode rnode;
BlockNumber blockNum; /* blknum relative to begin of reln */
} BufferTag;
#define CLEAR_BUFFERTAG(a) \
( \
- (a)->relId.dbId = InvalidOid, \
- (a)->relId.relId = InvalidOid, \
+ (a)->rnode.tblNode = InvalidOid, \
+ (a)->rnode.relNode = InvalidOid, \
(a)->blockNum = InvalidBlockNumber \
)
#define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \
( \
(a)->blockNum = (xx_blockNum), \
- (a)->relId = (xx_reln)->rd_lockInfo.lockRelId \
+ (a)->rnode = (xx_reln)->rd_node \
)
-#ifdef OLD_FILE_NAMING
-/* If we have to write a buffer "blind" (without a relcache entry),
- * the BufferTag is not enough information. BufferBlindId carries the
- * additional information needed.
+/*
+ * We don't need in this data any more but it allows more user
+ * friendly error messages. Feel free to get rid of it
+ * (and change a lot of places -:))
*/
typedef struct bufblindid
{
@@ -72,17 +72,6 @@ typedef struct bufblindid
char relname[NAMEDATALEN]; /* name of reln */
} BufferBlindId;
-#else
-
-typedef struct bufblindid
-{
- char dbname[NAMEDATALEN]; /* name of db in which buf belongs */
- char relname[NAMEDATALEN]; /* name of reln */
- RelFileNode rnode;
-} BufferBlindId;
-
-#endif
-
#define BAD_BUFFER_ID(bid) ((bid) < 1 || (bid) > NBuffers)
#define INVALID_DESCRIPTOR (-3)
@@ -120,7 +109,22 @@ typedef struct sbufdesc
bool ri_lock; /* read-intent lock */
bool w_lock; /* context exclusively locked */
- BufferBlindId blind; /* extra info to support blind write */
+ /*
+ * 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.
+ */
+ LockRelId relId;
+ BufferBlindId blind; /* was used to support blind write */
} BufferDesc;
/*
@@ -187,6 +191,7 @@ extern long *PrivateRefCount;
extern bits8 *BufferLocks;
extern BufferTag *BufferTagLastDirtied;
extern BufferBlindId *BufferBlindLastDirtied;
+extern LockRelId *BufferRelidLastDirtied;
extern bool *BufferDirtiedByMe;
extern SPINLOCK BufMgrLock;
diff --git a/src/include/storage/relfilenode.h b/src/include/storage/relfilenode.h
index de4d1e1beea..ee6e2c22805 100644
--- a/src/include/storage/relfilenode.h
+++ b/src/include/storage/relfilenode.h
@@ -15,4 +15,8 @@ typedef struct RelFileNode
Oid relNode; /* relation */
} RelFileNode;
+#define RelFileNodeEquals(node1, node2) \
+ ((node1).relNode == (node2).relNode && \
+ (node2).tblNode == (node2).tblNode)
+
#endif /* RELFILENODE_H */