v2-0001-Invalidate-Buffer-By-Bufnum.patch
application/octet-stream
Filename: v2-0001-Invalidate-Buffer-By-Bufnum.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Invalidate Buffer By Bufnum
| File | + | − |
|---|---|---|
| contrib/pg_buffercache/Makefile | 1 | 1 |
| contrib/pg_buffercache/meson.build | 1 | 0 |
| contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql | 6 | 0 |
| contrib/pg_buffercache/pg_buffercache.control | 1 | 1 |
| contrib/pg_buffercache/pg_buffercache_pages.c | 34 | 0 |
| src/backend/storage/buffer/bufmgr.c | 71 | 0 |
| src/include/storage/bufmgr.h | 3 | 0 |
| v1-0001-Invalidate-Buffer-By-Bufnum.patch | 191 | 0 |
From 80165aa62e3ba54ac04f6465c9a39380c2932c25 Mon Sep 17 00:00:00 2001
From: Palak <palakchaturvedi2843@gmail.com>
Date: Fri, 30 Jun 2023 08:21:06 +0000
Subject: [PATCH v2] Invalidate Buffer By Bufnum
---
contrib/pg_buffercache/Makefile | 2 +-
contrib/pg_buffercache/meson.build | 1 +
.../pg_buffercache--1.4--1.5.sql | 6 +
contrib/pg_buffercache/pg_buffercache.control | 2 +-
contrib/pg_buffercache/pg_buffercache_pages.c | 34 ++++
src/backend/storage/buffer/bufmgr.c | 71 +++++++
src/include/storage/bufmgr.h | 3 +
v1-0001-Invalidate-Buffer-By-Bufnum.patch | 191 ++++++++++++++++++
8 files changed, 308 insertions(+), 2 deletions(-)
create mode 100644 contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
create mode 100644 v1-0001-Invalidate-Buffer-By-Bufnum.patch
diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
index d6b58d4da9..eae65ead9e 100644
--- a/contrib/pg_buffercache/Makefile
+++ b/contrib/pg_buffercache/Makefile
@@ -8,7 +8,7 @@ OBJS = \
EXTENSION = pg_buffercache
DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \
pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \
- pg_buffercache--1.3--1.4.sql
+ pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql
PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
REGRESS = pg_buffercache
diff --git a/contrib/pg_buffercache/meson.build b/contrib/pg_buffercache/meson.build
index c51edf37d1..748463bc19 100644
--- a/contrib/pg_buffercache/meson.build
+++ b/contrib/pg_buffercache/meson.build
@@ -22,6 +22,7 @@ install_data(
'pg_buffercache--1.2--1.3.sql',
'pg_buffercache--1.2.sql',
'pg_buffercache--1.3--1.4.sql',
+ 'pg_buffercache--1.4--1.5.sql',
'pg_buffercache.control',
kwargs: contrib_data_args,
)
diff --git a/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql b/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
new file mode 100644
index 0000000000..c96848c77d
--- /dev/null
+++ b/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
@@ -0,0 +1,6 @@
+\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.5'" to load this file. \quit
+
+CREATE FUNCTION pg_buffercache_invalidate(IN int, IN bool default true)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'pg_buffercache_invalidate'
+LANGUAGE C PARALLEL SAFE;
diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
index a82ae5f9bb..5ee875f77d 100644
--- a/contrib/pg_buffercache/pg_buffercache.control
+++ b/contrib/pg_buffercache/pg_buffercache.control
@@ -1,5 +1,5 @@
# pg_buffercache extension
comment = 'examine the shared buffer cache'
-default_version = '1.4'
+default_version = '1.5'
module_pathname = '$libdir/pg_buffercache'
relocatable = true
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 3316732365..93ee4ef724 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -64,6 +64,40 @@ PG_FUNCTION_INFO_V1(pg_buffercache_pages);
PG_FUNCTION_INFO_V1(pg_buffercache_summary);
PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
+PG_FUNCTION_INFO_V1(pg_buffercache_invalidate);
+Datum
+pg_buffercache_invalidate(PG_FUNCTION_ARGS)
+{
+ Buffer bufnum;
+ bool result;
+ bool force;
+
+ if (PG_ARGISNULL(0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("buffernum cannot be NULL")));
+ }
+
+ bufnum = PG_GETARG_INT32(0);
+ if (bufnum <= 0 || bufnum > NBuffers)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("buffernum is not valid")));
+
+ }
+
+ /*
+ * Check whether to force invalidate the dirty buffer. The default value of force is true.
+ */
+
+ force = PG_GETARG_BOOL(1);
+
+ result = TryInvalidateBuffer(bufnum, force);
+ PG_RETURN_BOOL(result);
+}
+
Datum
pg_buffercache_pages(PG_FUNCTION_ARGS)
{
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 3c59bbd04e..5b874a83ae 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -5592,3 +5592,74 @@ TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
(errcode(ERRCODE_SNAPSHOT_TOO_OLD),
errmsg("snapshot too old")));
}
+
+/*
+ * Try Invalidating a buffer using bufnum.
+ * If the buffer is invalid, the function returns false.
+ * The function checks for dirty buffer and flushes the dirty buffer before invalidating.
+ * If the buffer is still dirty it returns false.
+ */
+bool
+TryInvalidateBuffer(Buffer bufnum, bool force)
+{
+ BufferDesc *bufHdr = GetBufferDescriptor(bufnum - 1);
+ uint32 buf_state;
+ ReservePrivateRefCountEntry();
+
+ buf_state = LockBufHdr(bufHdr);
+ if ((buf_state & BM_VALID) == BM_VALID)
+ {
+ /*
+ * The buffer is pinned therefore cannot invalidate.
+ */
+ if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
+ {
+ UnlockBufHdr(bufHdr, buf_state);
+ return false;
+ }
+ if ((buf_state & BM_DIRTY) == BM_DIRTY)
+ {
+ /*
+ * If the buffer is dirty and the user has not asked to clear the dirty buffer return false.
+ * Otherwise clear the dirty buffer.
+ */
+ if(!force){
+ return false;
+ }
+ /*
+ * Try once to flush the dirty buffer.
+ */
+ ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+ PinBuffer_Locked(bufHdr);
+ LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
+ FlushBuffer(bufHdr, NULL, IOOBJECT_RELATION, IOCONTEXT_NORMAL);
+ LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
+ UnpinBuffer(bufHdr);
+ buf_state = LockBufHdr(bufHdr);
+ if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
+ {
+ UnlockBufHdr(bufHdr, buf_state);
+ return false;
+ }
+
+ /*
+ * If its dirty again or not valid anymore give up.
+ */
+
+ if ((buf_state & (BM_DIRTY | BM_VALID)) != (BM_VALID))
+ {
+ UnlockBufHdr(bufHdr, buf_state);
+ return false;
+ }
+
+ }
+
+ InvalidateBuffer(bufHdr);
+ return true;
+ }
+ else
+ {
+ UnlockBufHdr(bufHdr, buf_state);
+ return false;
+ }
+}
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 0f5fb6be00..1fdb7ae3f0 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -252,6 +252,9 @@ extern bool BgBufferSync(struct WritebackContext *wb_context);
extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
+
+extern bool TryInvalidateBuffer(Buffer bufnum, bool force);
+
/* in buf_init.c */
extern void InitBufferPool(void);
extern Size BufferShmemSize(void);
diff --git a/v1-0001-Invalidate-Buffer-By-Bufnum.patch b/v1-0001-Invalidate-Buffer-By-Bufnum.patch
new file mode 100644
index 0000000000..7ee605f88e
--- /dev/null
+++ b/v1-0001-Invalidate-Buffer-By-Bufnum.patch
@@ -0,0 +1,191 @@
+From 02ea352d84ed87e156617de8b8020811680cb412 Mon Sep 17 00:00:00 2001
+From: Palak <palakchaturvedi2843@gmail.com>
+Date: Fri, 30 Jun 2023 08:21:06 +0000
+Subject: [PATCH v1] Invalidate Buffer By Bufnum
+
+---
+ contrib/pg_buffercache/Makefile | 2 +-
+ contrib/pg_buffercache/meson.build | 1 +
+ .../pg_buffercache--1.4--1.5.sql | 6 ++
+ contrib/pg_buffercache/pg_buffercache.control | 2 +-
+ contrib/pg_buffercache/pg_buffercache_pages.c | 27 ++++++++
+ src/backend/storage/buffer/bufmgr.c | 64 +++++++++++++++++++
+ src/include/storage/bufmgr.h | 3 +
+ 7 files changed, 103 insertions(+), 2 deletions(-)
+ create mode 100644 contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
+
+diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
+index d6b58d4da9..eae65ead9e 100644
+--- a/contrib/pg_buffercache/Makefile
++++ b/contrib/pg_buffercache/Makefile
+@@ -8,7 +8,7 @@ OBJS = \
+ EXTENSION = pg_buffercache
+ DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \
+ pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \
+- pg_buffercache--1.3--1.4.sql
++ pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql
+ PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
+
+ REGRESS = pg_buffercache
+diff --git a/contrib/pg_buffercache/meson.build b/contrib/pg_buffercache/meson.build
+index c51edf37d1..748463bc19 100644
+--- a/contrib/pg_buffercache/meson.build
++++ b/contrib/pg_buffercache/meson.build
+@@ -22,6 +22,7 @@ install_data(
+ 'pg_buffercache--1.2--1.3.sql',
+ 'pg_buffercache--1.2.sql',
+ 'pg_buffercache--1.3--1.4.sql',
++ 'pg_buffercache--1.4--1.5.sql',
+ 'pg_buffercache.control',
+ kwargs: contrib_data_args,
+ )
+diff --git a/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql b/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
+new file mode 100644
+index 0000000000..c7e47456d7
+--- /dev/null
++++ b/contrib/pg_buffercache/pg_buffercache--1.4--1.5.sql
+@@ -0,0 +1,6 @@
++\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.5'" to load this file. \quit
++
++CREATE FUNCTION pg_buffercache_invalidate(IN int)
++RETURNS bool
++AS 'MODULE_PATHNAME', 'pg_buffercache_invalidate'
++LANGUAGE C PARALLEL SAFE;
+diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
+index a82ae5f9bb..5ee875f77d 100644
+--- a/contrib/pg_buffercache/pg_buffercache.control
++++ b/contrib/pg_buffercache/pg_buffercache.control
+@@ -1,5 +1,5 @@
+ # pg_buffercache extension
+ comment = 'examine the shared buffer cache'
+-default_version = '1.4'
++default_version = '1.5'
+ module_pathname = '$libdir/pg_buffercache'
+ relocatable = true
+diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
+index 3316732365..6dd02fe6af 100644
+--- a/contrib/pg_buffercache/pg_buffercache_pages.c
++++ b/contrib/pg_buffercache/pg_buffercache_pages.c
+@@ -64,6 +64,33 @@ PG_FUNCTION_INFO_V1(pg_buffercache_pages);
+ PG_FUNCTION_INFO_V1(pg_buffercache_summary);
+ PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
+
++PG_FUNCTION_INFO_V1(pg_buffercache_invalidate);
++Datum
++pg_buffercache_invalidate(PG_FUNCTION_ARGS)
++{
++ Buffer bufnum;
++ bool result;
++
++ if (PG_ARGISNULL(0))
++ {
++ ereport(ERROR,
++ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
++ errmsg("buffernum cannot be NULL")));
++ }
++
++ bufnum = PG_GETARG_INT32(0);
++ if (bufnum < 0 || bufnum > NBuffers)
++ {
++ ereport(ERROR,
++ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
++ errmsg("buffernum is not valid")));
++
++ }
++
++ result = TryInvalidateBuffer(bufnum);
++ PG_RETURN_BOOL(result);
++}
++
+ Datum
+ pg_buffercache_pages(PG_FUNCTION_ARGS)
+ {
+diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
+index 3c59bbd04e..376afcf996 100644
+--- a/src/backend/storage/buffer/bufmgr.c
++++ b/src/backend/storage/buffer/bufmgr.c
+@@ -5592,3 +5592,67 @@ TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
+ (errcode(ERRCODE_SNAPSHOT_TOO_OLD),
+ errmsg("snapshot too old")));
+ }
++
++/*
++Try Invalidating a buffer using bufnum.
++If the buffer is invalid, the function returns false.
++The function checks for dirty buffer and flushes the dirty buffer before invalidating.
++If the buffer is still dirty it returns false.
++*/
++bool
++TryInvalidateBuffer(Buffer bufnum)
++{
++ BufferDesc *bufHdr = GetBufferDescriptor(bufnum - 1);
++ uint32 buf_state;
++
++ ReservePrivateRefCountEntry();
++
++ buf_state = LockBufHdr(bufHdr);
++ if ((buf_state & BM_VALID) == BM_VALID)
++ {
++ /*
++ * The buffer is pinned therefore cannot invalidate.
++ */
++ if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
++ {
++ UnlockBufHdr(bufHdr, buf_state);
++ return false;
++ }
++ if ((buf_state & BM_DIRTY) == BM_DIRTY)
++ {
++ /*
++ * Try once to flush the dirty buffer.
++ */
++ PinBuffer_Locked(bufHdr);
++ LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
++ FlushBuffer(bufHdr, NULL, IOOBJECT_RELATION, IOCONTEXT_NORMAL);
++ LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
++ UnpinBuffer(bufHdr);
++ buf_state = LockBufHdr(bufHdr);
++ if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
++ {
++ UnlockBufHdr(bufHdr, buf_state);
++ return false;
++ }
++
++ /*
++ * If its dirty again or not valid anymore give up.
++ */
++
++ if ((buf_state & (BM_DIRTY | BM_VALID)) != (BM_VALID))
++ {
++ UnlockBufHdr(bufHdr, buf_state);
++ return false;
++ }
++
++ }
++
++ InvalidateBuffer(bufHdr);
++ return true;
++ }
++ else
++ {
++ UnlockBufHdr(bufHdr, buf_state);
++ return false;
++ }
++}
+diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
+index 0f5fb6be00..4ba3d9089b 100644
+--- a/src/include/storage/bufmgr.h
++++ b/src/include/storage/bufmgr.h
+@@ -252,6 +252,9 @@ extern bool BgBufferSync(struct WritebackContext *wb_context);
+
+ extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
+
++
++extern bool TryInvalidateBuffer(Buffer bufnum);
++
+ /* in buf_init.c */
+ extern void InitBufferPool(void);
+ extern Size BufferShmemSize(void);
+--
+2.25.1
+
--
2.25.1