From 63f1316b2c160b72bdc1bcff6272e2888fce0db4 Mon Sep 17 00:00:00 2001 From: bdrouvotAWS Date: Sat, 5 Aug 2023 12:39:42 +0000 Subject: [PATCH v2] pg_wait_event Adding a new system view, namely pg_wait_event, that describes the wait events. --- doc/src/sgml/system-views.sgml | 55 ++++++++++++++ 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 | 76 +++++++++++++------ 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 | 3 + src/test/regress/expected/sysviews.out | 8 ++ src/test/regress/sql/sysviews.sql | 4 + src/tools/msvc/clean.bat | 1 + 13 files changed, 183 insertions(+), 26 deletions(-) 19.8% doc/src/sgml/ 60.6% src/backend/utils/activity/ 5.3% src/include/catalog/ 5.7% src/test/regress/expected/ 3.0% src/test/regress/sql/ 5.3% src/ diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml index 57b228076e..e9cbeff682 100644 --- a/doc/src/sgml/system-views.sgml +++ b/doc/src/sgml/system-views.sgml @@ -221,6 +221,11 @@ views + + pg_wait_event + wait events + + @@ -4825,4 +4830,54 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + + <structname>pg_wait_event</structname> + + + pg_wait_event + + + + The view pg_wait_event provides description about the + wait events. + + + + <structname>pg_wait_event</structname> Columns + + + + + Column Type + + + Description + + + + + + + + wait_event_name text + + + Wait event name + + + + + + description texte + + + Wait event description + + + + +
+
+ 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..6f2b823b6b 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,76 @@ 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//$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", $wev->[1]; + printf $ic "\tvalues[1] = 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..9407d18254 --- /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 2 + 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..57d8875dee 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}', + proargmodes => '{o,o}', proargnames => '{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..23b5f7dbca 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2631,6 +2631,9 @@ 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_name, + description + FROM pg_get_wait_events() we(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..12309be267 100644 --- a/src/test/regress/expected/sysviews.out +++ b/src/test/regress/expected/sysviews.out @@ -134,6 +134,14 @@ select name, setting from pg_settings where name like 'enable%'; enable_tidscan | on (21 rows) +-- There will surely be at least 240 wait events and at least 27 related to WAL +select count(*) > 239 as ok, count(*) FILTER (WHERE description like '%WAL%') > 26 AS ok_wal_desc + from pg_wait_event; + ok | ok_wal_desc +----+------------- + 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..6bc6bd1322 100644 --- a/src/test/regress/sql/sysviews.sql +++ b/src/test/regress/sql/sysviews.sql @@ -55,6 +55,10 @@ 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 240 wait events and at least 27 related to WAL +select 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