aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r--src/backend/storage/buffer/bufmgr.c120
1 files changed, 69 insertions, 51 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index b8d3e51b5d5..d5ff24df022 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.110 2001/05/10 20:38:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.111 2001/05/12 19:58:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -88,10 +88,10 @@ extern void AbortBufferIO(void);
*/
#define BUFFER_IS_BROKEN(buf) ((buf->flags & BM_IO_ERROR) && !(buf->flags & BM_DIRTY))
-static Buffer ReadBufferWithBufferLock(Relation relation, BlockNumber blockNum,
- bool bufferLockHeld);
+static Buffer ReadBufferInternal(Relation reln, BlockNumber blockNum,
+ bool isExtend, bool bufferLockHeld);
static BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum,
- bool *foundPtr, bool bufferLockHeld);
+ bool *foundPtr);
static int ReleaseBufferWithBufferLock(Buffer buffer);
static int BufferReplace(BufferDesc *bufHdr);
void PrintBufferDescs(void);
@@ -121,7 +121,7 @@ RelationGetBufferWithBuffer(Relation relation,
SpinRelease(BufMgrLock);
return buffer;
}
- return ReadBufferWithBufferLock(relation, blockNumber, true);
+ return ReadBufferInternal(relation, blockNumber, false, true);
}
else
{
@@ -131,7 +131,7 @@ RelationGetBufferWithBuffer(Relation relation,
return buffer;
}
}
- return ReadBuffer(relation, blockNumber);
+ return ReadBufferInternal(relation, blockNumber, false, false);
}
/*
@@ -152,38 +152,44 @@ RelationGetBufferWithBuffer(Relation relation,
/*
* ReadBuffer
- *
*/
Buffer
ReadBuffer(Relation reln, BlockNumber blockNum)
{
- return ReadBufferWithBufferLock(reln, blockNum, false);
+ return ReadBufferInternal(reln, blockNum, false, false);
}
/*
- * ReadBufferWithBufferLock -- does the work of
- * ReadBuffer() but with the possibility that
- * the buffer lock has already been held. this
- * is yet another effort to reduce the number of
- * semops in the system.
+ * ReadBufferInternal -- internal version of ReadBuffer with more options
+ *
+ * isExtend: if true, assume that we are extending the file and the caller
+ * is passing the current EOF block number (ie, caller already called
+ * smgrnblocks()).
+ *
+ * bufferLockHeld: if true, caller already acquired the bufmgr spinlock.
+ * (This is assumed never to be true if dealing with a local buffer!)
*/
static Buffer
-ReadBufferWithBufferLock(Relation reln,
- BlockNumber blockNum,
- bool bufferLockHeld)
+ReadBufferInternal(Relation reln, BlockNumber blockNum,
+ bool isExtend, bool bufferLockHeld)
{
BufferDesc *bufHdr;
int status;
bool found;
- bool extend; /* extending the file by one block */
bool isLocalBuf;
- extend = (blockNum == P_NEW);
isLocalBuf = reln->rd_myxactonly;
if (isLocalBuf)
{
ReadLocalBufferCount++;
+ /* Substitute proper block number if caller asked for P_NEW */
+ if (blockNum == P_NEW)
+ {
+ blockNum = reln->rd_nblocks;
+ reln->rd_nblocks++;
+ isExtend = true;
+ }
bufHdr = LocalBufferAlloc(reln, blockNum, &found);
if (found)
LocalBufferHitCount++;
@@ -191,16 +197,25 @@ ReadBufferWithBufferLock(Relation reln,
else
{
ReadBufferCount++;
-
+ /* Substitute proper block number if caller asked for P_NEW */
+ if (blockNum == P_NEW)
+ {
+ blockNum = smgrnblocks(DEFAULT_SMGR, reln);
+ isExtend = true;
+ }
/*
* lookup the buffer. IO_IN_PROGRESS is set if the requested
* block is not currently in memory.
*/
- bufHdr = BufferAlloc(reln, blockNum, &found, bufferLockHeld);
+ if (!bufferLockHeld)
+ SpinAcquire(BufMgrLock);
+ bufHdr = BufferAlloc(reln, blockNum, &found);
if (found)
BufferHitCount++;
}
+ /* At this point we do NOT hold the bufmgr spinlock. */
+
if (!bufHdr)
return InvalidBuffer;
@@ -208,11 +223,11 @@ ReadBufferWithBufferLock(Relation reln,
if (found)
{
/*
- * Could see found && extend if a buffer was already created for
+ * Could have found && isExtend if a buffer was already created for
* the next page position, but then smgrextend failed to write
* the page. Must fall through and try to extend file again.
*/
- if (!extend)
+ if (!isExtend)
return BufferDescriptorGetBuffer(bufHdr);
}
@@ -220,16 +235,16 @@ ReadBufferWithBufferLock(Relation reln,
* if we have gotten to this point, the reln pointer must be ok and
* the relation file must be open.
*/
- if (extend)
+ if (isExtend)
{
/* new buffers are zero-filled */
MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ);
- status = smgrextend(DEFAULT_SMGR, reln, bufHdr->tag.blockNum,
+ status = smgrextend(DEFAULT_SMGR, reln, blockNum,
(char *) MAKE_PTR(bufHdr->data));
}
else
{
- status = smgrread(DEFAULT_SMGR, reln, bufHdr->tag.blockNum,
+ status = smgrread(DEFAULT_SMGR, reln, blockNum,
(char *) MAKE_PTR(bufHdr->data));
}
@@ -290,13 +305,13 @@ ReadBufferWithBufferLock(Relation reln,
*
* Returns: descriptor for buffer
*
- * When this routine returns, the BufMgrLock is guaranteed NOT be held.
+ * BufMgrLock must be held at entry. When this routine returns,
+ * the BufMgrLock is guaranteed NOT to be held.
*/
static BufferDesc *
BufferAlloc(Relation reln,
BlockNumber blockNum,
- bool *foundPtr,
- bool bufferLockHeld)
+ bool *foundPtr)
{
BufferDesc *buf,
*buf2;
@@ -305,16 +320,8 @@ BufferAlloc(Relation reln,
/* create a new tag so we can lookup the buffer */
/* assume that the relation is already open */
- if (blockNum == P_NEW)
- {
- blockNum = smgrnblocks(DEFAULT_SMGR, reln);
- }
-
INIT_BUFFERTAG(&newTag, reln, blockNum);
- if (!bufferLockHeld)
- SpinAcquire(BufMgrLock);
-
/* see if the block is in the buffer pool already */
buf = BufTableLookup(&newTag);
if (buf != NULL)
@@ -666,25 +673,34 @@ WriteNoReleaseBuffer(Buffer buffer)
#undef ReleaseAndReadBuffer
/*
* ReleaseAndReadBuffer -- combine ReleaseBuffer() and ReadBuffer()
- * so that only one semop needs to be called.
+ * to save a spinlock release/acquire.
*
+ * An additional frammish of this routine is that the caller may perform
+ * file extension (as if blockNum = P_NEW) by passing the actual current
+ * EOF block number as blockNum and setting isExtend true. This hack
+ * allows us to avoid calling smgrnblocks() again when the caller has
+ * already done it.
+ *
+ * Note: it is OK to pass buffer = InvalidBuffer, indicating that no old
+ * buffer actually needs to be released. This case is the same as ReadBuffer
+ * except for the isExtend option.
*/
Buffer
ReleaseAndReadBuffer(Buffer buffer,
Relation relation,
- BlockNumber blockNum)
+ BlockNumber blockNum,
+ bool isExtend)
{
BufferDesc *bufHdr;
- Buffer retbuf;
- if (BufferIsLocal(buffer))
- {
- Assert(LocalRefCount[-buffer - 1] > 0);
- LocalRefCount[-buffer - 1]--;
- }
- else
+ if (BufferIsValid(buffer))
{
- if (BufferIsValid(buffer))
+ if (BufferIsLocal(buffer))
+ {
+ Assert(LocalRefCount[-buffer - 1] > 0);
+ LocalRefCount[-buffer - 1]--;
+ }
+ else
{
bufHdr = &BufferDescriptors[buffer - 1];
Assert(PrivateRefCount[buffer - 1] > 0);
@@ -701,13 +717,14 @@ ReleaseAndReadBuffer(Buffer buffer,
AddBufferToFreelist(bufHdr);
bufHdr->flags |= BM_FREE;
}
- retbuf = ReadBufferWithBufferLock(relation, blockNum, true);
- return retbuf;
+ return ReadBufferInternal(relation, blockNum,
+ isExtend, true);
}
}
}
- return ReadBuffer(relation, blockNum);
+ return ReadBufferInternal(relation, blockNum,
+ isExtend, false);
}
/*
@@ -1735,13 +1752,14 @@ ReleaseAndReadBuffer_Debug(char *file,
int line,
Buffer buffer,
Relation relation,
- BlockNumber blockNum)
+ BlockNumber blockNum,
+ bool isExtend)
{
bool bufferValid;
Buffer b;
bufferValid = BufferIsValid(buffer);
- b = ReleaseAndReadBuffer(buffer, relation, blockNum);
+ b = ReleaseAndReadBuffer(buffer, relation, blockNum, isExtend);
if (ShowPinTrace && bufferValid && BufferIsLocal(buffer)
&& is_userbuffer(buffer))
{