Hi,
On 8/8/23 7:37 AM, Drouvot, Bertrand wrote:
Hi,
On 8/8/23 5:05 AM, Michael Paquier wrote:
On Tue, Aug 08, 2023 at 11:53:32AM +0900, Kyotaro Horiguchi wrote:
As I mentioned in another thread, I'm uncertain about our stance on
the class id of the wait event. If a class acts as a namespace, we
should include it in the view. Otherwise, if the class id is just an
attribute of the wait event, we should make the event name unique.
Including the class name in the view makes the most sense to me, FWIW,
as it could be also possible that one reuses an event name in the
existing in-core list, but for extensions. That's of course not
something I would recommend.
Thanks Kyotaro-san and Michael for the feedback. I do agree and will
add the class name.
Please find attached v3 adding the wait event types.
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
From b54aa2dd33835a83bfe08a99338874200512fdf0 Mon Sep 17 00:00:00 2001
From: bdrouvotAWS <bdrou...@amazon.com>
Date: Sat, 5 Aug 2023 12:39:42 +0000
Subject: [PATCH v3] pg_wait_event
Adding a new system view, namely pg_wait_event, that describes the wait events.
---
doc/src/sgml/system-views.sgml | 64 +++++++++++++++
src/backend/catalog/system_views.sql | 3 +
src/backend/utils/activity/.gitignore | 1 +
src/backend/utils/activity/Makefile | 6 +-
.../activity/generate-wait_event_types.pl | 77 +++++++++++++------
src/backend/utils/activity/meson.build | 1 +
src/backend/utils/activity/pg_wait_event.c | 41 ++++++++++
src/include/catalog/pg_proc.dat | 6 ++
src/include/utils/meson.build | 4 +-
src/test/regress/expected/rules.out | 4 +
src/test/regress/expected/sysviews.out | 11 +++
src/test/regress/sql/sysviews.sql | 7 ++
src/tools/msvc/clean.bat | 1 +
13 files changed, 200 insertions(+), 26 deletions(-)
21.6% doc/src/sgml/
56.7% src/backend/utils/activity/
5.2% src/include/catalog/
7.4% src/test/regress/expected/
4.0% src/test/regress/sql/
4.9% src/
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 57b228076e..ed26c8326f 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -221,6 +221,11 @@
<entry>views</entry>
</row>
+ <row>
+ <entry><link
linkend="view-pg-wait-event"><structname>pg_wait_event</structname></link></entry>
+ <entry>wait events</entry>
+ </row>
+
</tbody>
</tgroup>
</table>
@@ -4825,4 +4830,63 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</table>
</sect1>
+
+ <sect1 id="view-pg-wait-event">
+ <title><structname>pg_wait_event</structname></title>
+
+ <indexterm zone="view-pg-wait-event">
+ <primary>pg_wait_event</primary>
+ </indexterm>
+
+ <para>
+ The view <structname>pg_wait_event</structname> provides description about
the
+ wait events.
+ </para>
+
+ <table>
+ <title><structname>pg_wait_event</structname> Columns</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ Column Type
+ </para>
+ <para>
+ Description
+ </para></entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>wait_event_type</structfield> <type>text</type>
+ </para>
+ <para>
+ Wait event type
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>wait_event_name</structfield> <type>text</type>
+ </para>
+ <para>
+ Wait event name
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>description</structfield> <type>texte</type>
+ </para>
+ <para>
+ Wait event description
+ </para></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
</chapter>
diff --git a/src/backend/catalog/system_views.sql
b/src/backend/catalog/system_views.sql
index af65af6bdd..f86a4dd770 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1342,3 +1342,6 @@ CREATE VIEW pg_stat_subscription_stats AS
ss.stats_reset
FROM pg_subscription as s,
pg_stat_get_subscription_stats(s.oid) as ss;
+
+CREATE VIEW pg_wait_event AS
+ SELECT * FROM pg_get_wait_events() AS we;
diff --git a/src/backend/utils/activity/.gitignore
b/src/backend/utils/activity/.gitignore
index d77079285b..ad089a0b63 100644
--- a/src/backend/utils/activity/.gitignore
+++ b/src/backend/utils/activity/.gitignore
@@ -1,2 +1,3 @@
/pgstat_wait_event.c
/wait_event_types.h
+/pg_wait_event_insert.c
diff --git a/src/backend/utils/activity/Makefile
b/src/backend/utils/activity/Makefile
index f1117745d4..8595e6ea77 100644
--- a/src/backend/utils/activity/Makefile
+++ b/src/backend/utils/activity/Makefile
@@ -32,10 +32,14 @@ OBJS = \
pgstat_subscription.o \
pgstat_wal.o \
pgstat_xact.o \
+ pg_wait_event.o \
wait_event.o
include $(top_srcdir)/src/backend/common.mk
+pg_wait_event.o: pg_wait_event_insert.c
+pg_wait_event_insert.c: wait_event_types.h
+
wait_event.o: pgstat_wait_event.c
pgstat_wait_event.c: wait_event_types.h
touch $@
@@ -44,4 +48,4 @@ wait_event_types.h:
$(top_srcdir)/src/backend/utils/activity/wait_event_names.tx
$(PERL) $(srcdir)/generate-wait_event_types.pl --code $<
maintainer-clean: clean
- rm -f wait_event_types.h pgstat_wait_event.c
+ rm -f wait_event_types.h pgstat_wait_event.c pg_wait_event_insert.c
diff --git a/src/backend/utils/activity/generate-wait_event_types.pl
b/src/backend/utils/activity/generate-wait_event_types.pl
index 56335e8730..c3f58acb4b 100644
--- a/src/backend/utils/activity/generate-wait_event_types.pl
+++ b/src/backend/utils/activity/generate-wait_event_types.pl
@@ -4,6 +4,7 @@
# Generate wait events support files from wait_event_names.txt:
# - wait_event_types.h (if --code is passed)
# - pgstat_wait_event.c (if --code is passed)
+# - pg_wait_event_insert.c (if --code is passed)
# - wait_event_types.sgml (if --docs is passed)
#
# Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
@@ -98,8 +99,10 @@ if ($gen_code)
# multiple times.
my $htmp = "$output_path/wait_event_types.h.tmp$$";
my $ctmp = "$output_path/pgstat_wait_event.c.tmp$$";
+ my $ictmp = "$output_path/pg_wait_event_insert.c.tmp$$";
open my $h, '>', $htmp or die "Could not open $htmp: $!";
open my $c, '>', $ctmp or die "Could not open $ctmp: $!";
+ open my $ic, '>', $ictmp or die "Could not open $ictmp: $!";
my $header_comment =
'/*-------------------------------------------------------------------------
@@ -129,16 +132,17 @@ if ($gen_code)
printf $c $header_comment, 'pgstat_wait_event.c';
+ printf $ic $header_comment, 'pg_wait_event_insert.c';
+
# uc() is being used to force the comparison to be case-insensitive.
foreach my $waitclass (sort { uc($a) cmp uc($b) } keys %hashwe)
{
- # Don't generate .c and .h files for Extension, LWLock and
- # Lock, these are handled independently.
- next
- if ( $waitclass eq 'WaitEventExtension'
- || $waitclass eq 'WaitEventLWLock'
- || $waitclass eq 'WaitEventLock');
+ # Don't generate .c (except pg_wait_event_insert.c) and .h
files for
+ # Extension, LWLock and Lock, these are handled independently.
+ my $is_exception = $waitclass eq 'WaitEventExtension' ||
+ $waitclass eq
'WaitEventLWLock' ||
+ $waitclass eq
'WaitEventLock';
my $last = $waitclass;
$last =~ s/^WaitEvent//;
@@ -147,50 +151,77 @@ if ($gen_code)
my $firstpass = 1;
my $pg_wait_class;
- printf $c
- "static const char *\npgstat_get_wait_$lastlc($waitclass
w)\n{\n";
- printf $c "\tconst char *event_name = \"unknown wait
event\";\n\n";
- printf $c "\tswitch (w)\n\t{\n";
+ if (!$is_exception)
+ {
+ printf $c
+ "static const char
*\npgstat_get_wait_$lastlc($waitclass w)\n{\n";
+ printf $c "\tconst char *event_name = \"unknown wait
event\";\n\n";
+ printf $c "\tswitch (w)\n\t{\n";
+ }
foreach my $wev (@{ $hashwe{$waitclass} })
{
- if ($firstpass)
+ if ($firstpass && !$is_exception)
{
printf $h "typedef enum\n{\n";
$pg_wait_class = "PG_WAIT_" . $lastuc;
printf $h "\t%s = %s", $wev->[0],
$pg_wait_class;
$continue = ",\n";
}
- else
+ elsif (!$is_exception)
{
printf $h "%s\t%s", $continue, $wev->[0];
$continue = ",\n";
}
- $firstpass = 0;
- printf $c "\t\t case %s:\n", $wev->[0];
- # Apply quotes to the wait event name string.
- printf $c "\t\t\t event_name = \"%s\";\n\t\t\t
break;\n",
- $wev->[1];
+ if (!$is_exception)
+ {
+ $firstpass = 0;
+
+ printf $c "\t\t case %s:\n", $wev->[0];
+ # Apply quotes to the wait event name string.
+ printf $c "\t\t\t event_name = \"%s\";\n\t\t\t
break;\n",
+ $wev->[1];
+ }
+
+ my $new_desc = substr $wev->[2], 1, -2;
+ $new_desc =~ s/'/\\'/g;
+ $new_desc =~ s/<.*>(.*?)<.*>/$1/g;
+ $new_desc =~ s/<xref linkend="guc-(.*?)"\/>/$1/g;
+ $new_desc =~ s/; see.*$//;
+
+ printf $ic "\tmemset(values, 0, sizeof(values));\n";
+ printf $ic "\tmemset(nulls, 0, sizeof(nulls));\n\n";
+ printf $ic "\tvalues[0] =
CStringGetTextDatum(\"%s\");\n", $last;
+ printf $ic "\tvalues[1] =
CStringGetTextDatum(\"%s\");\n", $wev->[1];
+ printf $ic "\tvalues[2] =
CStringGetTextDatum(\"%s\");\n\n", $new_desc;
+
+ printf $ic "\ttuplestore_putvalues(rsinfo->setResult,
rsinfo->setDesc, values, nulls);\n\n";
}
- printf $h "\n} $waitclass;\n\n";
+ if (!$is_exception)
+ {
+ printf $h "\n} $waitclass;\n\n";
- printf $c
- "\t\t\t /* no default case, so that compiler will warn */\n";
- printf $c "\t}\n\n";
- printf $c "\treturn event_name;\n";
- printf $c "}\n\n";
+ printf $c
+ "\t\t\t /* no default case, so that compiler will
warn */\n";
+ printf $c "\t}\n\n";
+ printf $c "\treturn event_name;\n";
+ printf $c "}\n\n";
+ }
}
printf $h "#endif /* WAIT_EVENT_TYPES_H */\n";
close $h;
close $c;
+ close $ic;
rename($htmp, "$output_path/wait_event_types.h")
|| die "rename: $htmp to $output_path/wait_event_types.h: $!";
rename($ctmp, "$output_path/pgstat_wait_event.c")
|| die "rename: $ctmp to $output_path/pgstat_wait_event.c: $!";
+ rename($ictmp, "$output_path/pg_wait_event_insert.c")
+ || die "rename: $ictmp to $output_path/pg_wait_event_insert.c: $!";
}
# Generate the .sgml file.
elsif ($gen_docs)
diff --git a/src/backend/utils/activity/meson.build
b/src/backend/utils/activity/meson.build
index 9633f3623c..774e0bd348 100644
--- a/src/backend/utils/activity/meson.build
+++ b/src/backend/utils/activity/meson.build
@@ -23,6 +23,7 @@ backend_sources += files(
# seems nicer to not add that as an include path for the whole backend.
waitevent_sources = files(
'wait_event.c',
+ 'pg_wait_event.c',
)
wait_event = static_library('wait_event_names',
diff --git a/src/backend/utils/activity/pg_wait_event.c
b/src/backend/utils/activity/pg_wait_event.c
new file mode 100644
index 0000000000..e6bfe36d4d
--- /dev/null
+++ b/src/backend/utils/activity/pg_wait_event.c
@@ -0,0 +1,41 @@
+/* ----------
+ * pg_wait_event.c
+ * Wait event reporting infrastructure.
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/activity/pg_wait_event.c
+ *
+ * NOTES
+ *
+ * The "pg_wait_event_insert.c" included in this file is generated by
+ * src/backend/utils/activity/generate-wait_event_types.pl
+ *
+ */
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "utils/builtins.h"
+
+/*
+ * This function lists the wait events and their descriptions.
+ *
+ * The system view pg_wait_event provides a user interface to this
+ * SRF.
+ */
+Datum
+pg_get_wait_events(PG_FUNCTION_ARGS)
+{
+#define NUM_WAIT_EVENT_TABLES_ELEM 3
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ Datum values[NUM_WAIT_EVENT_TABLES_ELEM];
+ bool nulls[NUM_WAIT_EVENT_TABLES_ELEM];
+
+ /* Build tuplestore to hold the result rows */
+ InitMaterializedSRF(fcinfo, 0);
+
+ #include "pg_wait_event_insert.c"
+ return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6996073989..6d10d2e5be 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5417,6 +5417,12 @@
proargmodes =>
'{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
proargnames =>
'{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,gss_delegation,leader_pid,query_id}',
prosrc => 'pg_stat_get_activity' },
+{ oid => '8403', descr => 'describe wait events',
+ proname => 'pg_get_wait_events', procost => '10', prorows => '100',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,text,text}',
+ proargmodes => '{o,o,o}', proargnames =>
'{wait_event_type,wait_event_name,description}',
+ prosrc => 'pg_get_wait_events' },
{ oid => '3318',
descr => 'statistics: information about progress of backends running
maintenance command',
proname => 'pg_stat_get_progress_info', prorows => '100', proretset => 't',
diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build
index 6de5d93799..4f14f770ef 100644
--- a/src/include/utils/meson.build
+++ b/src/include/utils/meson.build
@@ -1,6 +1,6 @@
# Copyright (c) 2022-2023, PostgreSQL Global Development Group
-wait_event_output = ['wait_event_types.h', 'pgstat_wait_event.c']
+wait_event_output = ['wait_event_types.h', 'pgstat_wait_event.c',
'pg_wait_event_insert.c']
wait_event_target = custom_target('wait_event_names',
input: files('../../backend/utils/activity/wait_event_names.txt'),
output: wait_event_output,
@@ -11,7 +11,7 @@ wait_event_target = custom_target('wait_event_names',
],
build_by_default: true,
install: true,
- install_dir: [dir_include_server / 'utils', false],
+ install_dir: [dir_include_server / 'utils', false, false],
)
wait_event_types_h = wait_event_target[0]
diff --git a/src/test/regress/expected/rules.out
b/src/test/regress/expected/rules.out
index e07afcd4aa..f160cb5642 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2631,6 +2631,10 @@ pg_views| SELECT n.nspname AS schemaname,
FROM (pg_class c
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
WHERE (c.relkind = 'v'::"char");
+pg_wait_event| SELECT wait_event_type,
+ wait_event_name,
+ description
+ FROM pg_get_wait_events() we(wait_event_type, wait_event_name, description);
SELECT tablename, rulename, definition FROM pg_rules
WHERE schemaname = 'pg_catalog'
ORDER BY tablename, rulename;
diff --git a/src/test/regress/expected/sysviews.out
b/src/test/regress/expected/sysviews.out
index 001c6e7eb9..bcf251c0c8 100644
--- a/src/test/regress/expected/sysviews.out
+++ b/src/test/regress/expected/sysviews.out
@@ -134,6 +134,17 @@ select name, setting from pg_settings where name like
'enable%';
enable_tidscan | on
(21 rows)
+-- There will surely be at least 9 wait event types, 240 wait events and at
+-- least 27 related to WAL
+select count(distinct(wait_event_type)) > 8 as ok_type,
+ count(*) > 239 as ok,
+ count(*) FILTER (WHERE description like '%WAL%') > 26 AS ok_wal_desc
+from pg_wait_event;
+ ok_type | ok | ok_wal_desc
+---------+----+-------------
+ t | t | t
+(1 row)
+
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are
-- more-or-less working. We can't test their contents in any great detail
-- without the outputs changing anytime IANA updates the underlying data,
diff --git a/src/test/regress/sql/sysviews.sql
b/src/test/regress/sql/sysviews.sql
index 351e469c77..7a9dc6021d 100644
--- a/src/test/regress/sql/sysviews.sql
+++ b/src/test/regress/sql/sysviews.sql
@@ -55,6 +55,13 @@ select count(*) = 0 as ok from pg_stat_wal_receiver;
-- a regression test run.
select name, setting from pg_settings where name like 'enable%';
+-- There will surely be at least 9 wait event types, 240 wait events and at
+-- least 27 related to WAL
+select count(distinct(wait_event_type)) > 8 as ok_type,
+ count(*) > 239 as ok,
+ count(*) FILTER (WHERE description like '%WAL%') > 26 AS ok_wal_desc
+from pg_wait_event;
+
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are
-- more-or-less working. We can't test their contents in any great detail
-- without the outputs changing anytime IANA updates the underlying data,
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
index 7cb23ea894..028d174d87 100755
--- a/src/tools/msvc/clean.bat
+++ b/src/tools/msvc/clean.bat
@@ -55,6 +55,7 @@ if exist src\include\catalog\header-stamp del /q
src\include\catalog\header-stam
if exist doc\src\sgml\version.sgml del /q doc\src\sgml\version.sgml
if %DIST%==1 if exist src\backend\utils\activity\pgstat_wait_event.c del /q
src\backend\utils\activity\pgstat_wait_event.c
+if %DIST%==1 if exist src\backend\utils\activity\pg_wait_event_insert.c del /q
src\backend\utils\activity\pg_wait_event_insert.c
if %DIST%==1 if exist src\backend\utils\activity\wait_event_types.h del /q
src\backend\utils\activity\wait_event_types.h
if %DIST%==1 if exist src\backend\utils\fmgroids.h del /q
src\backend\utils\fmgroids.h
if %DIST%==1 if exist src\backend\utils\fmgrprotos.h del /q
src\backend\utils\fmgrprotos.h
--
2.34.1