Skip to content

Commit 5f591f2

Browse files
authored
Cherry-pick: Add pg_buffercache_usage_counts() to contrib/pg_buffercache. (#1492)
Turns out, `CREATE EXTENSION pg_buffercache` does not work on main. It is failing due pg_buffercache_usage_counts function is missing. This function was committed to PostgreSQL as part of postgres/postgres@f3fa313 Extension sql 1.4.1 version was cherry-picked to Cloudberry as part of #883 (see commit 79f2d28) ``` CREATE EXTENSION pg_buffercache; +ERROR: function pg_buffercache_usage_counts() does not exist ``` This pr fixes cherry-pick issues, and adds this extension to `ic-contrib` check Found during PG16 rebase work Original commit msg: It was pointed out that pg_buffercache_summary()'s report of the overall average usage count isn't that useful, and what would be more helpful in many cases is to report totals for each possible usage count. Add a new function to do it like that. Since pg_buffercache 1.4 is already new for v16, we don't need to create a new extension version; we'll just define this as part of 1.4. Nathan Bossart Discussion: https://postgr.es/m/20230130233040.GA2800702@nathanxps13
1 parent 110f8c1 commit 5f591f2

File tree

7 files changed

+177
-24
lines changed

7 files changed

+177
-24
lines changed

.github/workflows/build-cloudberry.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ jobs:
298298
"contrib/pgcrypto:installcheck",
299299
"contrib/tablefunc:installcheck",
300300
"contrib/passwordcheck:installcheck",
301+
"contrib/pg_buffercache:installcheck",
301302
"contrib/sslinfo:installcheck"]
302303
},
303304
{"test":"ic-gpcontrib",

.github/workflows/build-deb-cloudberry.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ jobs:
237237
"contrib/pgcrypto:installcheck",
238238
"contrib/tablefunc:installcheck",
239239
"contrib/passwordcheck:installcheck",
240+
"contrib/pg_buffercache:installcheck",
240241
"contrib/sslinfo:installcheck"]
241242
},
242243
{"test":"ic-deb-gpcontrib",

contrib/pg_buffercache/expected/pg_buffercache.out

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,24 @@ from pg_buffercache_summary();
1717
t | t | t
1818
(1 row)
1919

20+
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
21+
?column?
22+
----------
23+
t
24+
(1 row)
25+
2026
-- Check that the functions / views can't be accessed by default. To avoid
2127
-- having to create a dedicated user, use the pg_database_owner pseudo-role.
2228
SET ROLE pg_database_owner;
29+
SELECT * FROM pg_buffercache;
30+
ERROR: permission denied for view pg_buffercache
31+
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
32+
ERROR: permission denied for function pg_buffercache_pages
33+
SELECT * FROM pg_buffercache_summary();
34+
ERROR: permission denied for function pg_buffercache_summary
35+
SELECT * FROM pg_buffercache_usage_counts();
36+
ERROR: permission denied for function pg_buffercache_usage_counts
37+
RESET role;
2338
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
2439
?column?
2540
----------
@@ -72,17 +87,7 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated WHERE buffers >=
7287
(1 row)
7388

7489
-- Check that the functions / views can't be accessed by default.
75-
CREATE ROLE buffercache_test;
76-
SET ROLE buffercache_test;
77-
SELECT * FROM pg_buffercache;
78-
ERROR: permission denied for view pg_buffercache
79-
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
80-
ERROR: permission denied for function pg_buffercache_pages
81-
SELECT * FROM pg_buffercache_summary();
82-
ERROR: permission denied for function pg_buffercache_summary
83-
RESET role;
84-
SELECT * FROM pg_buffercache_usage_counts();
85-
ERROR: permission denied for function pg_buffercache_usage_counts
90+
SET ROLE pg_database_owner;
8691
-- GPDB
8792
SELECT * FROM pg_buffercache_summary;
8893
ERROR: permission denied for view pg_buffercache_summary
@@ -166,4 +171,3 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated;
166171
(1 row)
167172

168173
RESET ROLE;
169-
DROP ROLE buffercache_test;

contrib/pg_buffercache/pg_buffercache--1.3--1.4.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ CREATE FUNCTION pg_buffercache_summary(
1212
AS 'MODULE_PATHNAME', 'pg_buffercache_summary'
1313
LANGUAGE C PARALLEL SAFE;
1414

15+
CREATE FUNCTION pg_buffercache_usage_counts(
16+
OUT usage_count int4,
17+
OUT buffers int4,
18+
OUT dirty int4,
19+
OUT pinned int4)
20+
RETURNS SETOF record
21+
AS 'MODULE_PATHNAME', 'pg_buffercache_usage_counts'
22+
LANGUAGE C PARALLEL SAFE;
23+
1524
-- Don't want these to be available to public.
1625
REVOKE ALL ON FUNCTION pg_buffercache_summary() FROM PUBLIC;
1726
GRANT EXECUTE ON FUNCTION pg_buffercache_summary() TO pg_monitor;
27+
REVOKE ALL ON FUNCTION pg_buffercache_usage_counts() FROM PUBLIC;
28+
GRANT EXECUTE ON FUNCTION pg_buffercache_usage_counts() TO pg_monitor;

contrib/pg_buffercache/pg_buffercache_pages.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8
1919
#define NUM_BUFFERCACHE_PAGES_ELEM 9
2020
#define NUM_BUFFERCACHE_SUMMARY_ELEM 5
21+
#define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4
2122

2223
PG_MODULE_MAGIC;
2324

@@ -61,6 +62,7 @@ typedef struct
6162
*/
6263
PG_FUNCTION_INFO_V1(pg_buffercache_pages);
6364
PG_FUNCTION_INFO_V1(pg_buffercache_summary);
65+
PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts);
6466

6567
Datum
6668
pg_buffercache_pages(PG_FUNCTION_ARGS)
@@ -304,3 +306,44 @@ pg_buffercache_summary(PG_FUNCTION_ARGS)
304306

305307
PG_RETURN_DATUM(result);
306308
}
309+
310+
Datum
311+
pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
312+
{
313+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
314+
int usage_counts[BM_MAX_USAGE_COUNT + 1] = {0};
315+
int dirty[BM_MAX_USAGE_COUNT + 1] = {0};
316+
int pinned[BM_MAX_USAGE_COUNT + 1] = {0};
317+
Datum values[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM];
318+
bool nulls[NUM_BUFFERCACHE_USAGE_COUNTS_ELEM] = {0};
319+
320+
InitMaterializedSRF(fcinfo, 0);
321+
322+
for (int i = 0; i < NBuffers; i++)
323+
{
324+
BufferDesc *bufHdr = GetBufferDescriptor(i);
325+
uint32 buf_state = pg_atomic_read_u32(&bufHdr->state);
326+
int usage_count;
327+
328+
usage_count = BUF_STATE_GET_USAGECOUNT(buf_state);
329+
usage_counts[usage_count]++;
330+
331+
if (buf_state & BM_DIRTY)
332+
dirty[usage_count]++;
333+
334+
if (BUF_STATE_GET_REFCOUNT(buf_state) > 0)
335+
pinned[usage_count]++;
336+
}
337+
338+
for (int i = 0; i < BM_MAX_USAGE_COUNT + 1; i++)
339+
{
340+
values[0] = Int32GetDatum(i);
341+
values[1] = Int32GetDatum(usage_counts[i]);
342+
values[2] = Int32GetDatum(dirty[i]);
343+
values[3] = Int32GetDatum(pinned[i]);
344+
345+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
346+
}
347+
348+
return (Datum) 0;
349+
}

contrib/pg_buffercache/sql/pg_buffercache.sql

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ select buffers_used + buffers_unused > 0,
1010
buffers_pinned <= buffers_used
1111
from pg_buffercache_summary();
1212

13+
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
14+
1315
-- Check that the functions / views can't be accessed by default. To avoid
1416
-- having to create a dedicated user, use the pg_database_owner pseudo-role.
1517
SET ROLE pg_database_owner;
1618
SELECT * FROM pg_buffercache;
1719
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
1820
SELECT * FROM pg_buffercache_summary();
21+
SELECT * FROM pg_buffercache_usage_counts();
1922
RESET role;
2023
SELECT count(*) > 0 FROM pg_buffercache_usage_counts() WHERE buffers >= 0;
2124

@@ -42,12 +45,7 @@ SELECT count(*) > 0 FROM gp_buffercache_usage_counts WHERE buffers >= 0;
4245
SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated WHERE buffers >= 0;
4346

4447
-- Check that the functions / views can't be accessed by default.
45-
CREATE ROLE buffercache_test;
46-
SET ROLE buffercache_test;
47-
SELECT * FROM pg_buffercache;
48-
SELECT * FROM pg_buffercache_pages() AS p (wrong int);
49-
SELECT * FROM pg_buffercache_summary();
50-
SELECT * FROM pg_buffercache_usage_counts();
48+
SET ROLE pg_database_owner;
5149
-- GPDB
5250
SELECT * FROM pg_buffercache_summary;
5351
SELECT * FROM pg_buffercache_usage_counts;
@@ -73,5 +71,3 @@ SELECT buffers_used + buffers_unused > 0 FROM gp_buffercache_summary_aggregated;
7371
SELECT count(*) > 0 FROM gp_buffercache_usage_counts;
7472
SELECT count(*) > 0 FROM gp_buffercache_usage_counts_aggregated;
7573
RESET ROLE;
76-
77-
DROP ROLE buffercache_test;

doc/src/sgml/pgbuffercache.sgml

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@
2121
</indexterm>
2222

2323
<para>
24-
The module provides the <function>pg_buffercache_pages()</function>
25-
function, wrapped in the <structname>pg_buffercache</structname> view, and
26-
the <function>pg_buffercache_summary()</function> function.
24+
This module provides the <function>pg_buffercache_pages()</function>
25+
function (wrapped in the <structname>pg_buffercache</structname> view),
26+
the <function>pg_buffercache_summary()</function> function, and the
27+
<function>pg_buffercache_usage_counts()</function> function.
2728
</para>
2829

2930
<para>
@@ -38,6 +39,12 @@
3839
row summarizing the state of the shared buffer cache.
3940
</para>
4041

42+
<para>
43+
The <function>pg_buffercache_usage_counts()</function> function returns a set
44+
of records, each row describing the number of buffers with a given usage
45+
count.
46+
</para>
47+
4148
<para>
4249
By default, use is restricted to superusers and roles with privileges of the
4350
<literal>pg_monitor</literal> role. Access may be granted to others
@@ -242,7 +249,7 @@
242249
<structfield>usagecount_avg</structfield> <type>float8</type>
243250
</para>
244251
<para>
245-
Average usagecount of used shared buffers
252+
Average usage count of used shared buffers
246253
</para></entry>
247254
</row>
248255
</tbody>
@@ -266,6 +273,84 @@
266273
</sect2>
267274

268275
<sect2>
276+
<title>The <function>pg_buffercache_usage_counts()</function> Function</title>
277+
278+
<para>
279+
The definitions of the columns exposed by the function are shown in
280+
<xref linkend="pgbuffercache_usage_counts-columns"/>.
281+
</para>
282+
283+
<table id="pgbuffercache_usage_counts-columns">
284+
<title><function>pg_buffercache_usage_counts()</function> Output Columns</title>
285+
<tgroup cols="1">
286+
<thead>
287+
<row>
288+
<entry role="catalog_table_entry"><para role="column_definition">
289+
Column Type
290+
</para>
291+
<para>
292+
Description
293+
</para></entry>
294+
</row>
295+
</thead>
296+
297+
<tbody>
298+
<row>
299+
<entry role="catalog_table_entry"><para role="column_definition">
300+
<structfield>usage_count</structfield> <type>int4</type>
301+
</para>
302+
<para>
303+
A possible buffer usage count
304+
</para></entry>
305+
</row>
306+
307+
<row>
308+
<entry role="catalog_table_entry"><para role="column_definition">
309+
<structfield>buffers</structfield> <type>int4</type>
310+
</para>
311+
<para>
312+
Number of buffers with the usage count
313+
</para></entry>
314+
</row>
315+
316+
<row>
317+
<entry role="catalog_table_entry"><para role="column_definition">
318+
<structfield>dirty</structfield> <type>int4</type>
319+
</para>
320+
<para>
321+
Number of dirty buffers with the usage count
322+
</para></entry>
323+
</row>
324+
325+
<row>
326+
<entry role="catalog_table_entry"><para role="column_definition">
327+
<structfield>pinned</structfield> <type>int4</type>
328+
</para>
329+
<para>
330+
Number of pinned buffers with the usage count
331+
</para></entry>
332+
</row>
333+
</tbody>
334+
</tgroup>
335+
</table>
336+
337+
<para>
338+
The <function>pg_buffercache_usage_counts()</function> function returns a
339+
set of rows summarizing the states of all shared buffers, aggregated over
340+
the possible usage count values. Similar and more detailed information is
341+
provided by the <structname>pg_buffercache</structname> view, but
342+
<function>pg_buffercache_usage_counts()</function> is significantly cheaper.
343+
</para>
344+
345+
<para>
346+
Like the <structname>pg_buffercache</structname> view,
347+
<function>pg_buffercache_usage_counts()</function> does not acquire buffer
348+
manager locks. Therefore concurrent activity can lead to minor inaccuracies
349+
in the result.
350+
</para>
351+
</sect2>
352+
353+
<sect2 id="pgbuffercache-sample-output">
269354
<title>Sample Output</title>
270355

271356
<screen>
@@ -299,6 +384,18 @@ regression=# SELECT * FROM pg_buffercache_summary();
299384
--------------+----------------+---------------+----------------+----------------
300385
248 | 2096904 | 39 | 0 | 3.141129
301386
(1 row)
387+
388+
389+
regression=# SELECT * FROM pg_buffercache_usage_counts();
390+
usage_count | buffers | dirty | pinned
391+
-------------+---------+-------+--------
392+
0 | 14650 | 0 | 0
393+
1 | 1436 | 671 | 0
394+
2 | 102 | 88 | 0
395+
3 | 23 | 21 | 0
396+
4 | 9 | 7 | 0
397+
5 | 164 | 106 | 0
398+
(6 rows)
302399
</screen>
303400
</sect2>
304401

0 commit comments

Comments
 (0)