Skip to content

Commit 417bc37

Browse files
author
Commitfest Bot
committed
[CF 5694] v8 - Add pg_buffercache_mark_dirty[_all]() functions to the pg_buffercache
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5694 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAN55FZ32bsRUrcLoTWCApdmwaXrFVTovH07Pke-VCn=hBmtgzA@mail.gmail.com Author(s): Nazir Bilal Yavuz
2 parents 8b18ed6 + 66f9709 commit 417bc37

File tree

10 files changed

+497
-10
lines changed

10 files changed

+497
-10
lines changed

contrib/pg_buffercache/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ EXTENSION = pg_buffercache
99
DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \
1010
pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \
1111
pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql \
12-
pg_buffercache--1.5--1.6.sql
12+
pg_buffercache--1.5--1.6.sql pg_buffercache--1.6--1.7.sql
1313
PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time"
1414

1515
REGRESS = pg_buffercache pg_buffercache_numa

contrib/pg_buffercache/expected/pg_buffercache.out

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ SELECT count(*) > 0 FROM pg_buffercache_usage_counts();
5757

5858
RESET role;
5959
------
60-
---- Test pg_buffercache_evict* functions
60+
---- Test pg_buffercache_evict* and pg_buffercache_mark_dirty* functions
6161
------
6262
CREATE ROLE regress_buffercache_normal;
6363
SET ROLE regress_buffercache_normal;
@@ -68,6 +68,12 @@ SELECT * FROM pg_buffercache_evict_relation(1);
6868
ERROR: must be superuser to use pg_buffercache_evict_relation()
6969
SELECT * FROM pg_buffercache_evict_all();
7070
ERROR: must be superuser to use pg_buffercache_evict_all()
71+
SELECT * FROM pg_buffercache_mark_dirty(1);
72+
ERROR: must be superuser to use pg_buffercache_mark_dirty()
73+
SELECT * FROM pg_buffercache_mark_dirty_relation(1);
74+
ERROR: must be superuser to use pg_buffercache_mark_dirty_relation()
75+
SELECT * FROM pg_buffercache_mark_dirty_all();
76+
ERROR: must be superuser to use pg_buffercache_mark_dirty_all()
7177
RESET ROLE;
7278
-- These should return nothing, because these are STRICT functions
7379
SELECT * FROM pg_buffercache_evict(NULL);
@@ -82,6 +88,18 @@ SELECT * FROM pg_buffercache_evict_relation(NULL);
8288
| |
8389
(1 row)
8490

91+
SELECT * FROM pg_buffercache_mark_dirty(NULL);
92+
buffer_dirtied | buffer_already_dirty
93+
----------------+----------------------
94+
|
95+
(1 row)
96+
97+
SELECT * FROM pg_buffercache_mark_dirty_relation(NULL);
98+
buffers_dirtied | buffers_already_dirty | buffers_skipped
99+
-----------------+-----------------------+-----------------
100+
| |
101+
(1 row)
102+
85103
-- These should fail because they are not called by valid range of buffers
86104
-- Number of the shared buffers are limited by max integer
87105
SELECT 2147483647 max_buffers \gset
@@ -91,11 +109,18 @@ SELECT * FROM pg_buffercache_evict(0);
91109
ERROR: bad buffer ID: 0
92110
SELECT * FROM pg_buffercache_evict(:max_buffers);
93111
ERROR: bad buffer ID: 2147483647
94-
-- This should fail because pg_buffercache_evict_relation() doesn't accept
95-
-- local relations
112+
SELECT * FROM pg_buffercache_mark_dirty(-1);
113+
ERROR: bad buffer ID: -1
114+
SELECT * FROM pg_buffercache_mark_dirty(0);
115+
ERROR: bad buffer ID: 0
116+
SELECT * FROM pg_buffercache_mark_dirty(:max_buffers);
117+
ERROR: bad buffer ID: 2147483647
118+
-- These should fail because they don't accept local relations
96119
CREATE TEMP TABLE temp_pg_buffercache();
97120
SELECT * FROM pg_buffercache_evict_relation('temp_pg_buffercache');
98121
ERROR: relation uses local buffers, pg_buffercache_evict_relation() is intended to be used for shared buffers only
122+
SELECT * FROM pg_buffercache_mark_dirty_relation('temp_pg_buffercache');
123+
ERROR: relation uses local buffers, pg_buffercache_mark_dirty_relation() is intended to be used for shared buffers only
99124
DROP TABLE temp_pg_buffercache;
100125
-- These shouldn't fail
101126
SELECT buffer_evicted IS NOT NULL FROM pg_buffercache_evict(1);
@@ -117,5 +142,23 @@ SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_relation('shared_pg
117142
t
118143
(1 row)
119144

145+
SELECT buffers_dirtied IS NOT NULL FROM pg_buffercache_mark_dirty_relation('shared_pg_buffercache');
146+
?column?
147+
----------
148+
t
149+
(1 row)
150+
120151
DROP TABLE shared_pg_buffercache;
152+
SELECT pg_buffercache_mark_dirty(1) IS NOT NULL;
153+
?column?
154+
----------
155+
t
156+
(1 row)
157+
158+
SELECT pg_buffercache_mark_dirty_all() IS NOT NULL;
159+
?column?
160+
----------
161+
t
162+
(1 row)
163+
121164
DROP ROLE regress_buffercache_normal;

contrib/pg_buffercache/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ install_data(
2424
'pg_buffercache--1.3--1.4.sql',
2525
'pg_buffercache--1.4--1.5.sql',
2626
'pg_buffercache--1.5--1.6.sql',
27+
'pg_buffercache--1.6--1.7.sql',
2728
'pg_buffercache.control',
2829
kwargs: contrib_data_args,
2930
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* contrib/pg_buffercache/pg_buffercache--1.6--1.7.sql */
2+
3+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
4+
\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.7'" to load this file. \quit
5+
6+
CREATE FUNCTION pg_buffercache_mark_dirty(
7+
IN int,
8+
OUT buffer_dirtied boolean,
9+
OUT buffer_already_dirty boolean)
10+
AS 'MODULE_PATHNAME', 'pg_buffercache_mark_dirty'
11+
LANGUAGE C PARALLEL SAFE VOLATILE STRICT;
12+
13+
CREATE FUNCTION pg_buffercache_mark_dirty_relation(
14+
IN regclass,
15+
OUT buffers_dirtied int4,
16+
OUT buffers_already_dirty int4,
17+
OUT buffers_skipped int4)
18+
AS 'MODULE_PATHNAME', 'pg_buffercache_mark_dirty_relation'
19+
LANGUAGE C PARALLEL SAFE VOLATILE STRICT;
20+
21+
CREATE FUNCTION pg_buffercache_mark_dirty_all(
22+
OUT buffers_dirtied int4,
23+
OUT buffers_already_dirty int4,
24+
OUT buffers_skipped int4)
25+
AS 'MODULE_PATHNAME', 'pg_buffercache_mark_dirty_all'
26+
LANGUAGE C PARALLEL SAFE VOLATILE;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pg_buffercache extension
22
comment = 'examine the shared buffer cache'
3-
default_version = '1.6'
3+
default_version = '1.7'
44
module_pathname = '$libdir/pg_buffercache'
55
relocatable = true

contrib/pg_buffercache/pg_buffercache_pages.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
#define NUM_BUFFERCACHE_EVICT_ELEM 2
2626
#define NUM_BUFFERCACHE_EVICT_RELATION_ELEM 3
2727
#define NUM_BUFFERCACHE_EVICT_ALL_ELEM 3
28+
#define NUM_BUFFERCACHE_MARK_DIRTY_ELEM 2
29+
#define NUM_BUFFERCACHE_MARK_DIRTY_RELATION_ELEM 3
30+
#define NUM_BUFFERCACHE_MARK_DIRTY_ALL_ELEM 3
2831

2932
#define NUM_BUFFERCACHE_NUMA_ELEM 3
3033

@@ -100,6 +103,9 @@ PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
100103
PG_FUNCTION_INFO_V1(pg_buffercache_evict);
101104
PG_FUNCTION_INFO_V1(pg_buffercache_evict_relation);
102105
PG_FUNCTION_INFO_V1(pg_buffercache_evict_all);
106+
PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty);
107+
PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty_relation);
108+
PG_FUNCTION_INFO_V1(pg_buffercache_mark_dirty_all);
103109

104110

105111
/* Only need to touch memory once per backend process lifetime */
@@ -777,3 +783,120 @@ pg_buffercache_evict_all(PG_FUNCTION_ARGS)
777783

778784
PG_RETURN_DATUM(result);
779785
}
786+
787+
/*
788+
* Try to mark a shared buffer as dirty.
789+
*/
790+
Datum
791+
pg_buffercache_mark_dirty(PG_FUNCTION_ARGS)
792+
{
793+
794+
Datum result;
795+
TupleDesc tupledesc;
796+
HeapTuple tuple;
797+
Datum values[NUM_BUFFERCACHE_MARK_DIRTY_ELEM];
798+
bool nulls[NUM_BUFFERCACHE_MARK_DIRTY_ELEM] = {0};
799+
800+
Buffer buf = PG_GETARG_INT32(0);
801+
bool buffer_already_dirty;
802+
803+
if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
804+
elog(ERROR, "return type must be a row type");
805+
806+
pg_buffercache_superuser_check("pg_buffercache_mark_dirty");
807+
808+
if (buf < 1 || buf > NBuffers)
809+
elog(ERROR, "bad buffer ID: %d", buf);
810+
811+
812+
values[0] = BoolGetDatum(MarkDirtyUnpinnedBuffer(buf, &buffer_already_dirty));
813+
values[1] = BoolGetDatum(buffer_already_dirty);
814+
815+
tuple = heap_form_tuple(tupledesc, values, nulls);
816+
result = HeapTupleGetDatum(tuple);
817+
818+
PG_RETURN_DATUM(result);
819+
}
820+
821+
/*
822+
* Try to mark specified relation dirty.
823+
*/
824+
Datum
825+
pg_buffercache_mark_dirty_relation(PG_FUNCTION_ARGS)
826+
{
827+
Datum result;
828+
TupleDesc tupledesc;
829+
HeapTuple tuple;
830+
Datum values[NUM_BUFFERCACHE_MARK_DIRTY_RELATION_ELEM];
831+
bool nulls[NUM_BUFFERCACHE_MARK_DIRTY_RELATION_ELEM] = {0};
832+
833+
Oid relOid;
834+
Relation rel;
835+
836+
int32 buffers_already_dirty = 0;
837+
int32 buffers_dirtied = 0;
838+
int32 buffers_skipped = 0;
839+
840+
if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
841+
elog(ERROR, "return type must be a row type");
842+
843+
pg_buffercache_superuser_check("pg_buffercache_mark_dirty_relation");
844+
845+
relOid = PG_GETARG_OID(0);
846+
847+
rel = relation_open(relOid, AccessShareLock);
848+
849+
if (RelationUsesLocalBuffers(rel))
850+
ereport(ERROR,
851+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
852+
errmsg("relation uses local buffers, %s() is intended to be used for shared buffers only",
853+
"pg_buffercache_mark_dirty_relation")));
854+
855+
MarkDirtyRelUnpinnedBuffers(rel, &buffers_dirtied, &buffers_already_dirty,
856+
&buffers_skipped);
857+
858+
relation_close(rel, AccessShareLock);
859+
860+
values[0] = Int32GetDatum(buffers_dirtied);
861+
values[1] = Int32GetDatum(buffers_already_dirty);
862+
values[2] = Int32GetDatum(buffers_skipped);
863+
864+
tuple = heap_form_tuple(tupledesc, values, nulls);
865+
result = HeapTupleGetDatum(tuple);
866+
867+
PG_RETURN_DATUM(result);
868+
}
869+
870+
/*
871+
* Try to mark all the shared buffers as dirty.
872+
*/
873+
Datum
874+
pg_buffercache_mark_dirty_all(PG_FUNCTION_ARGS)
875+
{
876+
Datum result;
877+
TupleDesc tupledesc;
878+
HeapTuple tuple;
879+
Datum values[NUM_BUFFERCACHE_MARK_DIRTY_ALL_ELEM];
880+
bool nulls[NUM_BUFFERCACHE_MARK_DIRTY_ALL_ELEM] = {0};
881+
882+
int32 buffers_already_dirty = 0;
883+
int32 buffers_dirtied = 0;
884+
int32 buffers_skipped = 0;
885+
886+
if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE)
887+
elog(ERROR, "return type must be a row type");
888+
889+
pg_buffercache_superuser_check("pg_buffercache_mark_dirty_all");
890+
891+
MarkDirtyAllUnpinnedBuffers(&buffers_dirtied, &buffers_already_dirty,
892+
&buffers_skipped);
893+
894+
values[0] = Int32GetDatum(buffers_dirtied);
895+
values[1] = Int32GetDatum(buffers_already_dirty);
896+
values[2] = Int32GetDatum(buffers_skipped);
897+
898+
tuple = heap_form_tuple(tupledesc, values, nulls);
899+
result = HeapTupleGetDatum(tuple);
900+
901+
PG_RETURN_DATUM(result);
902+
}

contrib/pg_buffercache/sql/pg_buffercache.sql

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ RESET role;
3030

3131

3232
------
33-
---- Test pg_buffercache_evict* functions
33+
---- Test pg_buffercache_evict* and pg_buffercache_mark_dirty* functions
3434
------
3535

3636
CREATE ROLE regress_buffercache_normal;
@@ -40,31 +40,42 @@ SET ROLE regress_buffercache_normal;
4040
SELECT * FROM pg_buffercache_evict(1);
4141
SELECT * FROM pg_buffercache_evict_relation(1);
4242
SELECT * FROM pg_buffercache_evict_all();
43+
SELECT * FROM pg_buffercache_mark_dirty(1);
44+
SELECT * FROM pg_buffercache_mark_dirty_relation(1);
45+
SELECT * FROM pg_buffercache_mark_dirty_all();
4346

4447
RESET ROLE;
4548

4649
-- These should return nothing, because these are STRICT functions
4750
SELECT * FROM pg_buffercache_evict(NULL);
4851
SELECT * FROM pg_buffercache_evict_relation(NULL);
52+
SELECT * FROM pg_buffercache_mark_dirty(NULL);
53+
SELECT * FROM pg_buffercache_mark_dirty_relation(NULL);
4954

5055
-- These should fail because they are not called by valid range of buffers
5156
-- Number of the shared buffers are limited by max integer
5257
SELECT 2147483647 max_buffers \gset
5358
SELECT * FROM pg_buffercache_evict(-1);
5459
SELECT * FROM pg_buffercache_evict(0);
5560
SELECT * FROM pg_buffercache_evict(:max_buffers);
61+
SELECT * FROM pg_buffercache_mark_dirty(-1);
62+
SELECT * FROM pg_buffercache_mark_dirty(0);
63+
SELECT * FROM pg_buffercache_mark_dirty(:max_buffers);
5664

57-
-- This should fail because pg_buffercache_evict_relation() doesn't accept
58-
-- local relations
65+
-- These should fail because they don't accept local relations
5966
CREATE TEMP TABLE temp_pg_buffercache();
6067
SELECT * FROM pg_buffercache_evict_relation('temp_pg_buffercache');
68+
SELECT * FROM pg_buffercache_mark_dirty_relation('temp_pg_buffercache');
6169
DROP TABLE temp_pg_buffercache;
6270

6371
-- These shouldn't fail
6472
SELECT buffer_evicted IS NOT NULL FROM pg_buffercache_evict(1);
6573
SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_all();
6674
CREATE TABLE shared_pg_buffercache();
6775
SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_relation('shared_pg_buffercache');
76+
SELECT buffers_dirtied IS NOT NULL FROM pg_buffercache_mark_dirty_relation('shared_pg_buffercache');
6877
DROP TABLE shared_pg_buffercache;
78+
SELECT pg_buffercache_mark_dirty(1) IS NOT NULL;
79+
SELECT pg_buffercache_mark_dirty_all() IS NOT NULL;
6980

7081
DROP ROLE regress_buffercache_normal;

0 commit comments

Comments
 (0)