extend_bufmgr_api_for_hash_index_v1.patch
application/octet-stream
Filename: extend_bufmgr_api_for_hash_index_v1.patch
Type: application/octet-stream
Part: 0
Message:
Re: Hash Indexes
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| contrib/bloom/blutils.c | 1 | 1 |
| src/backend/access/gin/ginutil.c | 1 | 1 |
| src/backend/access/gist/gistutil.c | 1 | 1 |
| src/backend/access/nbtree/nbtpage.c | 1 | 1 |
| src/backend/access/spgist/spgdoinsert.c | 1 | 1 |
| src/backend/access/spgist/spgutils.c | 3 | 3 |
| src/backend/storage/buffer/bufmgr.c | 58 | 6 |
| src/include/storage/bufmgr.h | 2 | 1 |
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index b68a0d1..bcbf387 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -356,7 +356,7 @@ BloomNewBuffer(Relation index)
* We have to guard against the possibility that someone else already
* recycled this page; the buffer may be locked if so.
*/
- if (ConditionalLockBuffer(buffer))
+ if (ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
{
Page page = BufferGetPage(buffer);
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index f07eedc..75c516a 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -298,7 +298,7 @@ GinNewBuffer(Relation index)
* We have to guard against the possibility that someone else already
* recycled this page; the buffer may be locked if so.
*/
- if (ConditionalLockBuffer(buffer))
+ if (ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
{
Page page = BufferGetPage(buffer);
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 887c58b..607fe34 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -777,7 +777,7 @@ gistNewBuffer(Relation r)
* We have to guard against the possibility that someone else already
* recycled this page; the buffer may be locked if so.
*/
- if (ConditionalLockBuffer(buffer))
+ if (ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
{
Page page = BufferGetPage(buffer);
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 2001dc1..6434af0 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -614,7 +614,7 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
if (blkno == InvalidBlockNumber)
break;
buf = ReadBuffer(rel, blkno);
- if (ConditionalLockBuffer(buf))
+ if (ConditionalLockBuffer(buf, BUFFER_LOCK_EXCLUSIVE))
{
page = BufferGetPage(buf);
if (_bt_page_recyclable(page))
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 6fc04b2..2d38cb6 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -1997,7 +1997,7 @@ spgdoinsert(Relation index, SpGistState *state,
* held by a reader, or even just background writer/checkpointer
* process. Perhaps it'd be worth retrying after sleeping a bit?
*/
- if (!ConditionalLockBuffer(current.buffer))
+ if (!ConditionalLockBuffer(current.buffer, BUFFER_LOCK_EXCLUSIVE))
{
ReleaseBuffer(current.buffer);
UnlockReleaseBuffer(parent.buffer);
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index d570ae5..3adfa23 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -205,7 +205,7 @@ SpGistNewBuffer(Relation index)
* We have to guard against the possibility that someone else already
* recycled this page; the buffer may be locked if so.
*/
- if (ConditionalLockBuffer(buffer))
+ if (ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
{
Page page = BufferGetPage(buffer);
@@ -255,7 +255,7 @@ SpGistUpdateMetaPage(Relation index)
metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO);
- if (ConditionalLockBuffer(metabuffer))
+ if (ConditionalLockBuffer(metabuffer, BUFFER_LOCK_EXCLUSIVE))
{
metadata = SpGistPageGetMeta(BufferGetPage(metabuffer));
metadata->lastUsedPages = cache->lastUsedPages;
@@ -392,7 +392,7 @@ SpGistGetBuffer(Relation index, int flags, int needSpace, bool *isNew)
buffer = ReadBuffer(index, lup->blkno);
- if (!ConditionalLockBuffer(buffer))
+ if (!ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
{
/*
* buffer is locked by another process, so return a new buffer
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index df4c9d7..c1ab893 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3548,22 +3548,27 @@ LockBuffer(Buffer buffer, int mode)
/*
* Acquire the content_lock for the buffer, but only if we don't have to wait.
- *
- * This assumes the caller wants BUFFER_LOCK_EXCLUSIVE mode.
*/
bool
-ConditionalLockBuffer(Buffer buffer)
+ConditionalLockBuffer(Buffer buffer, int mode)
{
BufferDesc *buf;
Assert(BufferIsValid(buffer));
+ Assert(mode == BUFFER_LOCK_SHARE || mode == BUFFER_LOCK_EXCLUSIVE);
if (BufferIsLocal(buffer))
return true; /* act as though we got it */
buf = GetBufferDescriptor(buffer - 1);
- return LWLockConditionalAcquire(BufferDescriptorGetContentLock(buf),
- LW_EXCLUSIVE);
+ if (mode == BUFFER_LOCK_SHARE)
+ return LWLockConditionalAcquire(BufferDescriptorGetContentLock(buf),
+ LW_SHARED);
+ else if (mode == BUFFER_LOCK_EXCLUSIVE)
+ return LWLockConditionalAcquire(BufferDescriptorGetContentLock(buf),
+ LW_EXCLUSIVE);
+
+ return false;
}
/*
@@ -3724,7 +3729,7 @@ ConditionalLockBufferForCleanup(Buffer buffer)
return false;
/* Try to acquire lock */
- if (!ConditionalLockBuffer(buffer))
+ if (!ConditionalLockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE))
return false;
bufHdr = GetBufferDescriptor(buffer - 1);
@@ -3745,6 +3750,53 @@ ConditionalLockBufferForCleanup(Buffer buffer)
return false;
}
+/*
+ * IsBufferCleanupOK - as above, but don't attempt to take lock
+ *
+ * We won't loop, but just check once to see if the pin count is OK. If
+ * not, return FALSE.
+ */
+bool
+IsBufferCleanupOK(Buffer buffer)
+{
+ BufferDesc *bufHdr;
+ uint32 buf_state;
+
+ Assert(BufferIsValid(buffer));
+
+ if (BufferIsLocal(buffer))
+ {
+ /* There should be exactly one pin */
+ if (LocalRefCount[-buffer - 1] != 1)
+ return false;
+ /* Nobody else to wait for */
+ return true;
+ }
+
+ /* There should be exactly one local pin */
+ if (GetPrivateRefCount(buffer) != 1)
+ return false;
+
+ bufHdr = GetBufferDescriptor(buffer - 1);
+
+ /* caller must hold exclusive lock on buffer */
+ Assert(LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr),
+ LW_EXCLUSIVE));
+
+ buf_state = LockBufHdr(bufHdr);
+
+ Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0);
+ if (BUF_STATE_GET_REFCOUNT(buf_state) == 1)
+ {
+ /* pincount is OK. */
+ UnlockBufHdr(bufHdr, buf_state);
+ return true;
+ }
+
+ UnlockBufHdr(bufHdr, buf_state);
+ return false;
+}
+
/*
* Functions for buffer I/O handling
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 7b6ba96..fcb2bf2 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -224,9 +224,10 @@ extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
extern void UnlockBuffers(void);
extern void LockBuffer(Buffer buffer, int mode);
-extern bool ConditionalLockBuffer(Buffer buffer);
+extern bool ConditionalLockBuffer(Buffer buffer, int mode);
extern void LockBufferForCleanup(Buffer buffer);
extern bool ConditionalLockBufferForCleanup(Buffer buffer);
+extern bool IsBufferCleanupOK(Buffer buffer);
extern bool HoldingBufferPinThatDelaysRecovery(void);
extern void AbortBufferIO(void);