Hi,
Recently, the API to define custom wait events for extension is
supported.
* Change custom wait events to use dynamic shared hash tables(af720b4c5)
So, I'd like to rethink the wait event names for modules which use
"WAIT_EVENT_EXTENSION" wait events.
* postgres_fdw
* dblink
* pg_prewarm
* test_shm_mq
* worker_spi
I expect that no one will object to changing the names to appropriate
ones. But, we need to discuss that naming convention, the names
themselves,
document descriptions and so on.
I made the v1 patch
* CamelCase naming convention
* Add document descriptions for each module
I haven't added document descriptions for pg_prewarm and test modules.
The reason is that the wait event of autoprewarm is not shown on
pg_stat_activity. It's not an auxiliary-process and doesn't connect to
a database, so pgstat_bestart() isn't be called.
Feedback is always welcome and appreciated.
Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION
From 73c4c6562509465bea75a9bbd273298bdf0ee85e Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda <mshr.ik...@ntt.com>
Date: Fri, 18 Aug 2023 11:38:05 +0900
Subject: [PATCH] Make to use custom wait events for modules
---
contrib/dblink/dblink.c | 15 +++++-
contrib/pg_prewarm/autoprewarm.c | 13 ++++-
contrib/postgres_fdw/connection.c | 23 ++++++--
doc/src/sgml/dblink.sgml | 26 +++++++++
doc/src/sgml/postgres-fdw.sgml | 53 +++++++++++++++++++
doc/src/sgml/xfunc.sgml | 6 +--
src/test/modules/test_shm_mq/setup.c | 9 +++-
src/test/modules/test_shm_mq/test.c | 9 +++-
.../modules/worker_spi/t/001_worker_spi.pl | 8 +--
src/test/modules/worker_spi/worker_spi.c | 2 +-
10 files changed, 147 insertions(+), 17 deletions(-)
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 41e1f6c91d..26fcd093c7 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -130,6 +130,9 @@ static void restoreLocalGucs(int nestlevel);
static remoteConn *pconn = NULL;
static HTAB *remoteConnHash = NULL;
+/* value cached, fetched from shared memory */
+static uint32 wait_event_info = 0;
+
/*
* Following is list that holds multiple remote connections.
* Calling convention of each dblink function changes to accept
@@ -202,8 +205,12 @@ dblink_get_conn(char *conname_or_str,
connstr = conname_or_str;
dblink_connstr_check(connstr);
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info == 0)
+ wait_event_info = WaitEventExtensionNew("DblinkConnect");
+
/* OK to make connection */
- conn = libpqsrv_connect(connstr, WAIT_EVENT_EXTENSION);
+ conn = libpqsrv_connect(connstr, wait_event_info);
if (PQstatus(conn) == CONNECTION_BAD)
{
@@ -292,8 +299,12 @@ dblink_connect(PG_FUNCTION_ARGS)
/* check password in connection string if not superuser */
dblink_connstr_check(connstr);
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info == 0)
+ wait_event_info = WaitEventExtensionNew("DblinkConnect");
+
/* OK to make connection */
- conn = libpqsrv_connect(connstr, WAIT_EVENT_EXTENSION);
+ conn = libpqsrv_connect(connstr, wait_event_info);
if (PQstatus(conn) == CONNECTION_BAD)
{
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index d0efc9e524..8c2581f457 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -104,6 +104,7 @@ static AutoPrewarmSharedState *apw_state = NULL;
/* GUC variables. */
static bool autoprewarm = true; /* start worker? */
static int autoprewarm_interval = 300; /* dump interval */
+static uint32 wait_event_info = 0; /* value cached, fetched from shared memory */
/*
* Module load callback.
@@ -231,13 +232,21 @@ autoprewarm_main(Datum main_arg)
ProcessConfigFile(PGC_SIGHUP);
}
+ /*
+ * allocate or get the custom wait event though it will not be shown
+ * on pg_stat_activity because the autoprewarm worker doesn't connect
+ * a database.
+ */
+ if (wait_event_info == 0)
+ wait_event_info = WaitEventExtensionNew("PgPrewarmDumpDelay");
+
if (autoprewarm_interval <= 0)
{
/* We're only dumping at shutdown, so just wait forever. */
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_EXIT_ON_PM_DEATH,
-1L,
- WAIT_EVENT_EXTENSION);
+ wait_event_info);
}
else
{
@@ -264,7 +273,7 @@ autoprewarm_main(Datum main_arg)
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
delay_in_ms,
- WAIT_EVENT_EXTENSION);
+ wait_event_info);
}
/* Reset the latch, loop. */
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 7e12b722ec..c88624763d 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -83,6 +83,11 @@ static unsigned int prep_stmt_number = 0;
/* tracks whether any work is needed in callback functions */
static bool xact_got_connection = false;
+/* value cached, fetched from shared memory */
+static uint32 wait_event_info_connect = 0;
+static uint32 wait_event_info_receive = 0;
+static uint32 wait_event_info_cleanup_receive = 0;
+
/*
* Milliseconds to wait to cancel an in-progress query or execute a cleanup
* query; if it takes longer than 30 seconds to do these, we assume the
@@ -527,10 +532,14 @@ connect_pg_server(ForeignServer *server, UserMapping *user)
/* verify the set of connection parameters */
check_conn_params(keywords, values, user);
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info_connect == 0)
+ wait_event_info_connect = WaitEventExtensionNew("PostgresFdwConnect");
+
/* OK to make connection */
conn = libpqsrv_connect_params(keywords, values,
false, /* expand_dbname */
- WAIT_EVENT_EXTENSION);
+ wait_event_info_connect);
if (!conn || PQstatus(conn) != CONNECTION_OK)
ereport(ERROR,
@@ -858,12 +867,16 @@ pgfdw_get_result(PGconn *conn, const char *query)
{
int wc;
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info_receive == 0)
+ wait_event_info_receive = WaitEventExtensionNew("PostgresFdwReceive");
+
/* Sleep until there's something to do */
wc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE |
WL_EXIT_ON_PM_DEATH,
PQsocket(conn),
- -1L, WAIT_EVENT_EXTENSION);
+ -1L, wait_event_info_receive);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
@@ -1562,12 +1575,16 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result,
goto exit;
}
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info_cleanup_receive == 0)
+ wait_event_info_cleanup_receive = WaitEventExtensionNew("PostgresFdwCleanupReceive");
+
/* Sleep until there's something to do */
wc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE |
WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
PQsocket(conn),
- cur_timeout, WAIT_EVENT_EXTENSION);
+ cur_timeout, wait_event_info_cleanup_receive);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml
index 7d25f24f49..da6c4b7a92 100644
--- a/doc/src/sgml/dblink.sgml
+++ b/doc/src/sgml/dblink.sgml
@@ -101,6 +101,32 @@ dblink_connect(text connname, text connstr) returns text
</para>
</refsect1>
+ <refsect1>
+ <title>Wait Event</title>
+
+ <para>
+ <filename>dblink</filename> could show the following wait event under the wait
+ event type <literal>Extension</literal>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <literal>DblinkConnect</literal>
+ <indexterm>
+ <primary><literal>DblinkConnect</literal> wait event</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Waiting to establish connection to a remote server.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
<refsect1>
<title>Notes</title>
diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml
index 5062d712e7..c631e1384a 100644
--- a/doc/src/sgml/postgres-fdw.sgml
+++ b/doc/src/sgml/postgres-fdw.sgml
@@ -1042,6 +1042,59 @@ postgres=# SELECT postgres_fdw_disconnect_all();
</para>
</sect2>
+ <sect2 id="postgres-fdw-wait-events">
+ <title>Wait Events</title>
+
+ <para>
+ <filename>postgres_fdw</filename> could show the following wait events under the wait
+ event type <literal>Extension</literal>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <literal>PostgresFdwConnect</literal>
+ <indexterm>
+ <primary><literal>PostgresFdwConnect</literal> wait event</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Waiting to establish connection to a remote server.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <literal>PostgresFdwReceive</literal>
+ <indexterm>
+ <primary><literal>PostgresFdwReceive</literal> wait event</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Waiting to receive the results of a query from a remote server.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <literal>PostgresFdwCleanupReceive</literal>
+ <indexterm>
+ <primary><literal>PostgresFdwCleanupReceive</literal> wait event</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Waiting for same reason as <literal>PostgresFdwReceive</literal>, except that it's only for
+ abort.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect2>
+
<sect2 id="postgres-fdw-configuration-parameters">
<title>Configuration Parameters</title>
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 281c178b0e..96ba95818c 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3472,9 +3472,9 @@ uint32 WaitEventExtensionNew(const char *wait_event_name)
<screen>
=# SELECT wait_event_type, wait_event FROM pg_stat_activity
WHERE backend_type ~ 'worker_spi';
- wait_event_type | wait_event
------------------+-----------------
- Extension | worker_spi_main
+ wait_event_type | wait_event
+-----------------+---------------
+ Extension | WorkerSpiMain
(1 row)
</screen>
</para>
diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c
index 192e5cc2ab..ef68689d0b 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -40,6 +40,9 @@ static void wait_for_workers_to_become_ready(worker_state *wstate,
volatile test_shm_mq_header *hdr);
static bool check_worker_status(worker_state *wstate);
+/* value cached, fetched from shared memory */
+static uint32 wait_event_info_bgworker_startup = 0;
+
/*
* Set up a dynamic shared memory segment and zero or more background workers
* for a test run.
@@ -278,9 +281,13 @@ wait_for_workers_to_become_ready(worker_state *wstate,
break;
}
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info_bgworker_startup == 0)
+ wait_event_info_bgworker_startup = WaitEventExtensionNew("TestShmMqBgWorkerStartup");
+
/* Wait to be signaled. */
(void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
- WAIT_EVENT_EXTENSION);
+ wait_event_info_bgworker_startup);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
diff --git a/src/test/modules/test_shm_mq/test.c b/src/test/modules/test_shm_mq/test.c
index d9be703350..d7e8d3d868 100644
--- a/src/test/modules/test_shm_mq/test.c
+++ b/src/test/modules/test_shm_mq/test.c
@@ -28,6 +28,9 @@ PG_FUNCTION_INFO_V1(test_shm_mq_pipelined);
static void verify_message(Size origlen, char *origdata, Size newlen,
char *newdata);
+/* value cached, fetched from shared memory */
+static uint32 wait_event_info_message_queue = 0;
+
/*
* Simple test of the shared memory message queue infrastructure.
*
@@ -225,6 +228,10 @@ test_shm_mq_pipelined(PG_FUNCTION_ARGS)
if (wait)
{
+ /* first time, allocate or get the custom wait event */
+ if (wait_event_info_message_queue == 0)
+ wait_event_info_message_queue = WaitEventExtensionNew("TestShmMqMessageQueue");
+
/*
* If we made no progress, wait for one of the other processes to
* which we are connected to set our latch, indicating that they
@@ -232,7 +239,7 @@ test_shm_mq_pipelined(PG_FUNCTION_ARGS)
* for us to do.
*/
(void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
- WAIT_EVENT_EXTENSION);
+ wait_event_info_message_queue);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl
index 26b8a49bec..dac97be75f 100644
--- a/src/test/modules/worker_spi/t/001_worker_spi.pl
+++ b/src/test/modules/worker_spi/t/001_worker_spi.pl
@@ -43,9 +43,9 @@ is($result, qq(total|1), 'dynamic bgworker correctly consumed tuple data');
$result = $node->poll_query_until(
'postgres',
qq[SELECT wait_event FROM pg_stat_activity WHERE backend_type ~ 'worker_spi';],
- qq[worker_spi_main]);
+ qq[WorkerSpiMain]);
is($result, 1,
- 'dynamic bgworker has reported "worker_spi_main" as wait event');
+ 'dynamic bgworker has reported "WorkerSpiMain" as wait event');
note "testing bgworkers loaded with shared_preload_libraries";
@@ -68,7 +68,7 @@ ok( $node->poll_query_until(
'mydb',
qq[SELECT datname, count(datname), wait_event FROM pg_stat_activity
WHERE backend_type = 'worker_spi' GROUP BY datname, wait_event;],
- 'mydb|3|worker_spi_main'),
+ 'mydb|3|WorkerSpiMain'),
'bgworkers all launched'
) or die "Timed out while waiting for bgworkers to be launched";
@@ -83,7 +83,7 @@ ok( $node->poll_query_until(
qq[SELECT datname, count(datname), wait_event FROM pg_stat_activity
WHERE backend_type = 'worker_spi dynamic' AND
pid IN ($worker1_pid, $worker2_pid) GROUP BY datname, wait_event;],
- 'mydb|2|worker_spi_main'),
+ 'mydb|2|WorkerSpiMain'),
'dynamic bgworkers all launched'
) or die "Timed out while waiting for dynamic bgworkers to be launched";
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 98f8d4194b..2e3114990e 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -194,7 +194,7 @@ worker_spi_main(Datum main_arg)
/* First time, allocate or get the custom wait event */
if (worker_spi_wait_event_main == 0)
- worker_spi_wait_event_main = WaitEventExtensionNew("worker_spi_main");
+ worker_spi_wait_event_main = WaitEventExtensionNew("WorkerSpiMain");
/*
* Background workers mustn't call usleep() or any direct equivalent:
--
2.25.1