Re: Support to define custom wait events for extensions

2023-08-14 Thread Michael Paquier
On Tue, Aug 15, 2023 at 09:14:15AM +0900, Masahiro Ikeda wrote:
> OK. I'll make a new patch and start a new thread.

Cool, thanks!
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-14 Thread Masahiro Ikeda

On 2023-08-14 18:26, Michael Paquier wrote:

On Mon, Aug 14, 2023 at 05:55:42PM +0900, Masahiro Ikeda wrote:

I'm thinking a name like "contrib name + description summary" would
be nice. The "contrib name"  is namespace-like and the "description 
summary"
is the same as the name of the waiting event name in core. For 
example,
"DblinkConnect" for dblink. In the same as the core one, I thought the 
name

should be the camel case.


Or you could use something more in line with the other in-core wait
events formatted as camel-case, like DblinkConnect, etc.

BTW, is it better to discuss this in a new thread because other 
developers
might be interested in user-facing wait event names? I also would like 
to
add documentation on the wait events for each modules, as they are not 
mentioned

now.


Saying that, having some documentation on the page of each extension
is mandatory once these can be customized, in my opinion.  All that
should be discussed on a new, separate thread, to attract the correct
audience.


OK. I'll make a new patch and start a new thread.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-14 Thread Michael Paquier
On Mon, Aug 14, 2023 at 05:55:42PM +0900, Masahiro Ikeda wrote:
> I'm thinking a name like "contrib name + description summary" would
> be nice. The "contrib name"  is namespace-like and the "description summary"
> is the same as the name of the waiting event name in core. For example,
> "DblinkConnect" for dblink. In the same as the core one, I thought the name
> should be the camel case.

Or you could use something more in line with the other in-core wait
events formatted as camel-case, like DblinkConnect, etc.

> BTW, is it better to discuss this in a new thread because other developers
> might be interested in user-facing wait event names? I also would like to
> add documentation on the wait events for each modules, as they are not 
> mentioned
> now.

Saying that, having some documentation on the page of each extension
is mandatory once these can be customized, in my opinion.  All that
should be discussed on a new, separate thread, to attract the correct
audience.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-14 Thread Masahiro Ikeda

On 2023-08-14 15:28, Michael Paquier wrote:

On Mon, Aug 14, 2023 at 12:31:05PM +0900, Masahiro Ikeda wrote:

Thanks! I confirmed the changes, and all tests passed.


Okay, cool.  I got some extra time today and applied that, with a few
more tweaks.


Thanks for applying master branch!


This looks correct, but perhaps we need to think harder about the
custom event names and define a convention when more of this stuff is
added to the core modules.


I checked the source code how many functions use WAIT_EVENT_EXTENSION.
There are 3 contrib modules and a test module use WAIT_EVENT_EXTENSION 
and

there are 8 places where it is called as an argument.

* dblink
 - dblink_get_conn(): the wait event is set until the connection 
establishment succeeded

 - dblink_connect(): same as above

* autoprewarm
 - autoprewarm_main(): the wait event is set until shutdown request is 
received

 - autoprewarm_main(): the wait event is set until the next dump time

* postgres_fdw
 - connect_pg_server(): the wait event is set until connection 
establishment succeeded
 - pgfdw_get_result(): the wait event is set until the results are 
received

 - pgfdw_get_cleanup_result(): same as above except for abort cleanup

* test_sh_mq
 - wait_for_workers_to_become_ready(): the wait event is set until the 
workers become ready


I'm thinking a name like "contrib name + description summary" would
be nice. The "contrib name"  is namespace-like and the "description 
summary"

is the same as the name of the waiting event name in core. For example,
"DblinkConnect" for dblink. In the same as the core one, I thought the 
name

should be the camel case.

BTW, is it better to discuss this in a new thread because other 
developers
might be interested in user-facing wait event names? I also would like 
to add
documentation on the wait events for each modules, as they are not 
mentioned now.


Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-14 Thread Michael Paquier
On Mon, Aug 14, 2023 at 12:31:05PM +0900, Masahiro Ikeda wrote:
> Thanks! I confirmed the changes, and all tests passed.

Okay, cool.  I got some extra time today and applied that, with a few
more tweaks.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-13 Thread Masahiro Ikeda

On 2023-08-14 08:06, Michael Paquier wrote:

On Thu, Aug 10, 2023 at 05:37:55PM +0900, Michael Paquier wrote:

This looks correct, but perhaps we need to think harder about the
custom event names and define a convention when more of this stuff is
added to the core modules.


Okay, I have put my hands on that, fixing a couple of typos, polishing
a couple of comments, clarifying the docs and applying an indentation.
And here is a v4.

Any thoughts or comments?  I'd like to apply that soon, so as we are
able to move on with the wait event catalog and assigning custom wait
events to the other in-core modules.


Thanks! I confirmed the changes, and all tests passed.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-13 Thread Michael Paquier
On Thu, Aug 10, 2023 at 05:37:55PM +0900, Michael Paquier wrote:
> This looks correct, but perhaps we need to think harder about the
> custom event names and define a convention when more of this stuff is
> added to the core modules.

Okay, I have put my hands on that, fixing a couple of typos, polishing
a couple of comments, clarifying the docs and applying an indentation.
And here is a v4.

Any thoughts or comments?  I'd like to apply that soon, so as we are
able to move on with the wait event catalog and assigning custom wait
events to the other in-core modules.
--
Michael
From 83e40dace75d0df91e8b7f617bd03d02bd8450d4 Mon Sep 17 00:00:00 2001
From: Michael Paquier 
Date: Mon, 14 Aug 2023 07:48:15 +0900
Subject: [PATCH v4] Change custom wait events to use shared hash tables

Currently, names of the custom wait event must be registered for each
backends, requiring all these to link to the shared memory area of an
extention, even if not loaded with shared_preload_libraries.

This patch relaxes the constraints by storing the wait events and their
names in hash tables in shared memory.  First, this has the advantage to
simplify the registration of custom wait events to a single routine
call that returns an event ID, either existing or incremented:
uint32 WaitEventExtensionNew(const char *wait_event_name);

Any other backend looking at the wait event information, for instance
via pg_stat_activity, is then able to automatically know about the new
event name.

The code changes done in worker_spi show how things are simplified:
- worker_spi_init() is gone.
- No more shmem hooks.
- The custom wait event ID is cached in the process that needs to set
it, with one single call to WaitEventExtensionNew() to retrieve it.

Per suggestion from Andres Freund.

Author: Masahiro Ikeda
Discussion: https://postgr.es/m/20230801032349.aaiuvhtrcvvcw...@awork3.anarazel.de
---
 src/include/utils/wait_event.h|  18 +-
 src/backend/storage/lmgr/lwlocknames.txt  |   1 +
 src/backend/utils/activity/wait_event.c   | 217 +++---
 .../utils/activity/wait_event_names.txt   |   1 +
 .../modules/worker_spi/t/001_worker_spi.pl|  18 +-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 -
 src/test/modules/worker_spi/worker_spi.c  | 109 +
 doc/src/sgml/monitoring.sgml  |   5 +-
 doc/src/sgml/xfunc.sgml   |  26 +--
 src/tools/pgindent/typedefs.list  |   2 +
 10 files changed, 164 insertions(+), 238 deletions(-)

diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index aad8bc08fa..3cffae23e1 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -44,12 +44,14 @@ extern PGDLLIMPORT uint32 *my_wait_event_info;
  * Use this category when the server process is waiting for some condition
  * defined by an extension module.
  *
- * Extensions can define their own wait events in this category.  First,
- * they should call WaitEventExtensionNew() to get one or more wait event
- * IDs that are allocated from a shared counter.  These can be used directly
- * with pgstat_report_wait_start() or equivalent.  Next, each individual
- * process should call WaitEventExtensionRegisterName() to associate a wait
- * event string to the number allocated previously.
+ * Extensions can define their own wait events in this category.  They should
+ * call WaitEventExtensionNew() with a wait event string.  If the wait event
+ * associated the string is already allocated, it returns the wait event info.
+ * If not, it will get one wait event ID that is allocated from a shared
+ + counter, associate the string to the number in the shared dynamic hash and
+ * return the wait event info.
+ *
+ * The ID retrieved can be used with pgstat_report_wait_start() or equivalent.
  */
 typedef enum
 {
@@ -60,9 +62,7 @@ typedef enum
 extern void WaitEventExtensionShmemInit(void);
 extern Size WaitEventExtensionShmemSize(void);
 
-extern uint32 WaitEventExtensionNew(void);
-extern void WaitEventExtensionRegisterName(uint32 wait_event_info,
-		   const char *wait_event_name);
+extern uint32 WaitEventExtensionNew(const char *wait_event_name);
 
 /* --
  * pgstat_report_wait_start() -
diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt
index b34b6afecd..7af3e0ba1a 100644
--- a/src/backend/storage/lmgr/lwlocknames.txt
+++ b/src/backend/storage/lmgr/lwlocknames.txt
@@ -53,3 +53,4 @@ XactTruncationLock	44
 # 45 was XactTruncationLock until removal of BackendRandomLock
 WrapLimitsVacuumLock46
 NotifyQueueTailLock	47
+WaitEventExtensionLock  48
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index b3596ece80..14750233d4 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -45,6 +45,41 @@ uint32	   *my_wait_event_info = _my_wait_event_info;
 #define 

Re: Support to define custom wait events for extensions

2023-08-10 Thread Michael Paquier
On Thu, Aug 10, 2023 at 01:08:39PM +0900, Masahiro Ikeda wrote:
> In addition, I change the followings:
> * update about custom wait events in sgml. we don't need to use
>   shmem_startup_hook.
> * change the hash names for readability.
>  (ex. WaitEventExtensionNameHash -> WaitEventExtensionHashById)
> * fix a bug to fail to get already defined events by names
>   because HASH_BLOBS was specified. HASH_STRINGS is right since
>   the key is C strings.

That's what I get based on what ShmemInitHash() relies on.

I got a few more comments about v3.  Overall this looks much better.

This time the ordering of the operations in WaitEventExtensionNew()
looks much better.

+* The entry must be stored because it's registered in
+* WaitEventExtensionNew().
Not sure of the value added by this comment, I would remove it.

+   if (!entry)
+   elog(ERROR, "could not find the name for custom wait event ID %u",
+   eventId);

Or a simpler "could not find custom wait event name for ID %u"?

+static HTAB *WaitEventExtensionHashById;   /* find names from ids */
+static HTAB *WaitEventExtensionHashByName; /* find ids from names */

These names are OK here.

+/* Local variables */
+static uint32 worker_spi_wait_event = 0;
That's a cached value, used as a placeholder for the custom wait event
ID found from the table.

+HASH_ELEM | HASH_STRINGS);   /* key is Null-terminated C strings */
Looks obvious to me based on the code, I would remove this note.

+/* hash table entres */
s/entres/entries/

+   /*
+* Allocate and register a new wait event. But, we need to recheck because
+* other processes could already do so while releasing the lock.
+*/

Could be reworked for the second sentence, like "Recheck if the event
exists, as it could be possible that a concurrent process has inserted
one with the same name while the lock was previously released."

+   /* Recheck */
Duplicate.

/* OK to make connection */
-   conn = libpqsrv_connect(connstr, WAIT_EVENT_EXTENSION);
+   if (wait_event_info == 0)
+   wait_event_info = WaitEventExtensionNew("dblink_get_con");
+   conn = libpqsrv_connect(connstr, wait_event_info);

It is going to be difficult to make that simpler ;)

This looks correct, but perhaps we need to think harder about the
custom event names and define a convention when more of this stuff is
added to the core modules.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-09 Thread Masahiro Ikeda

Hi,

Thanks for your comments about the v2 patches. I updated to v3 patches.

The main changes are:
* remove the AddinShmemInitLock assertion
* add the new lock (WaitEventExtensionLock) to wait_event_names.txt
* change "static const int wee_hash_XXX_size" to "#define XXX"
* simplify worker_spi. I removed codes related to share memory and
  try to allocate the new wait event before waiting per background 
worker.

* change to elog from ereport because the errors are for developers.
* revise comments as advised.
* fix the request size for shared memory correctly
* simplify dblink.c
* fix process ordering of WaitEventExtensionNew() as advised to
  avoid leading illegal state.

In addition, I change the followings:
* update about custom wait events in sgml. we don't need to use
  shmem_startup_hook.
* change the hash names for readability.
 (ex. WaitEventExtensionNameHash -> WaitEventExtensionHashById)
* fix a bug to fail to get already defined events by names
  because HASH_BLOBS was specified. HASH_STRINGS is right since
  the key is C strings.

I create a new entry in commitfest for CI testing.
(https://commitfest.postgresql.org/44/4494/)

Thanks for closing the former entry.
(https://commitfest.postgresql.org/43/4368/)

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 234cc7d852aebf78285ccde383f27ea35a27dad2 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 10 Aug 2023 10:44:41 +0900
Subject: [PATCH 2/2] poc: custom wait event for dblink

---
 contrib/dblink/dblink.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 41e1f6c91d..b7158ecd4f 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -129,6 +129,7 @@ static void restoreLocalGucs(int nestlevel);
 /* Global */
 static remoteConn *pconn = NULL;
 static HTAB *remoteConnHash = NULL;
+static uint32 wait_event_info = 0;
 
 /*
  *	Following is list that holds multiple remote connections.
@@ -203,7 +204,9 @@ dblink_get_conn(char *conname_or_str,
 		dblink_connstr_check(connstr);
 
 		/* OK to make connection */
-		conn = libpqsrv_connect(connstr, WAIT_EVENT_EXTENSION);
+		if (wait_event_info == 0)
+			wait_event_info = WaitEventExtensionNew("dblink_get_con");
+		conn = libpqsrv_connect(connstr, wait_event_info);
 
 		if (PQstatus(conn) == CONNECTION_BAD)
 		{
-- 
2.25.1

From 07bbff06a0f58f08d313c02cbb4104ad1db2a0e9 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 10 Aug 2023 10:43:34 +0900
Subject: [PATCH 1/2] Change to manage custom wait events in shared hash

Currently, names of the custom wait event must be registered
per backends. This patch relaxes the constraints by store the
wait events and their names in hash tables in shared memory.

So, all backends can look up the wait event names on
pg_stat_activity view without additional processing by extensions.

In addition, extensions which do not use shared memory for their
use can define custom wait events because WaitEventExtensionNew()
will never allocate new one if the wait event associated to the
name is already allocated. It use hash table to identify uniqueness.
---
 doc/src/sgml/monitoring.sgml  |   7 +-
 doc/src/sgml/xfunc.sgml   |  26 +--
 src/backend/storage/lmgr/lwlocknames.txt  |   1 +
 src/backend/utils/activity/wait_event.c   | 219 +++---
 .../utils/activity/wait_event_names.txt   |   1 +
 src/include/utils/wait_event.h|  17 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  18 +-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 -
 src/test/modules/worker_spi/worker_spi.c  | 109 +
 9 files changed, 165 insertions(+), 238 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f4fc5d814f..19181832d7 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1121,10 +1121,9 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
  LWLock types
  to the list shown in  and
  . In some cases, the name
- assigned by an extension will not be available in all server processes;
- so an Extension or LWLock wait
- event might be reported as just
- extension rather than the
+ of LWLock assigned by an extension will not be
+ available in all server processes; so an wait event might be reported
+ as just extension rather than the
  extension-assigned name.
 

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index d6345a775b..281c178b0e 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3454,33 +3454,15 @@ if (!ptr)

 

-Shared Memory and Custom Wait Events
+Custom Wait Events
 
 
  Add-ins can define custom wait events under the wait event type
- Extension. The add-in's shared library must be
- preloaded by specifying it in shared_preload_libraries,
- and register a shmem_request_hook and a
-  

Re: Support to define custom wait events for extensions

2023-08-09 Thread Michael Paquier
On Wed, Aug 09, 2023 at 08:10:42PM +0900, Masahiro Ikeda wrote:
> * create second hash table to find a event id from a name to
>   identify uniquness. It enable extensions which don't use share
>   memory for their use to define custom wait events because
>   WaitEventExtensionNew() will not allocate duplicate wait events.

Okay, a second hash table to check if events are registered works for
me.

> * create PoC patch to show that extensions, which don't use shared
>   memory for their use, can define custom wait events.
>  (v2-0002-poc-custom-wait-event-for-dblink.patch)
> 
> I'm worrying about
> * Is 512(wee_hash_max_size) the maximum number of the custom wait
>   events sufficient?

Thanks for sending a patch!

I'm OK to start with that.  This could always be revisited later, but
even for a server loaded with a bunch of extensions that looks more
than enough to me.

> * Is there any way to not force extensions that don't use shared
>   memory for their use like dblink to acquire AddinShmemInitLock?;

Yes, they don't need it at all as the dynahashes are protected with
their own LWLocks.

+++ b/src/backend/storage/lmgr/lwlocknames.txt
@@ -53,3 +53,4 @@ XactTruncationLock44
 # 45 was XactTruncationLock until removal of BackendRandomLock
 WrapLimitsVacuumLock   46
 NotifyQueueTailLock47
+WaitEventExtensionLock  48

This new LWLock needs to be added to wait_event_names.txt, or it won't
be reported to pg_stat_activity and it would not be documented when
the sgml docs are generated from the txt data.

-extern uint32 WaitEventExtensionNew(void);
-extern void WaitEventExtensionRegisterName(uint32 wait_event_info,
-  const char *wait_event_name);
+extern uint32 WaitEventExtensionNew(const char *wait_event_name);
Looks about right, and the docs are refreshed.

+static const int wee_hash_init_size = 128;
+static const int wee_hash_max_size = 512;
I would use a few #defines with upper-case characters here instead as
these are constants for us.

Now that it is possible to rely on LWLocks for the hash tables, more
cleanup is possible in worker_spi, with the removal of
worker_spi_state, the shmem hooks and their routines.  The only thing
that should be needed is something like that at the start of
worker_spi_main() (same position as worker_spi_shmem_init now):
+static uint32 wait_event = 0;
[...]
+   if (wait_event == 0)
+   wait_event = WaitEventExtensionNew("worker_spi_main");

The updates in 001_worker_spi.pl look OK.

+* The entry must be stored because it's registered in
+* WaitEventExtensionNew().
 */
-   eventId -= NUM_BUILTIN_WAIT_EVENT_EXTENSION;
+   if (!entry)
+   ereport(ERROR,
+   errmsg("could not find the name for custom wait event ID %u", 
eventId));
Yeah, I think that's better than just falling back to "extension".  An
ID reported in pg_stat_activity should always have an entry, or we
have race conditions.  This should be an elog(ERROR), as in
this-error-shall-never-happen.  No need to translate the error string,
as well (the docs have been updated with this change. thanks!).

Additionally, LWLockHeldByMeInMode(AddinShmemInitLock) in
WaitEventExtensionNew() should not be needed, thanks to
WaitEventExtensionLock.

+ * WaitEventExtensionNameHash is used to find the name from a event id.
+ * It enables all backends look up them without additional processing
+ * per backend like LWLockRegisterTranche().

It does not seem necessary to mention LWLockRegisterTranche().

+ * WaitEventExtensionIdHash is used to find the event id from a name.
+ * Since it can identify uniquness by the names, extensions that do not
+ * use shared memory also be able to define custom wait events without
+ * defining duplicate wait events.

Perhaps this could just say that this table is necessary to ensure
that we don't have duplicated entries when registering new strings
with their IDs?  s/uniquness/uniqueness/.  The second part of the
sentence about shared memory does not seem necessary now.

+   sz = add_size(sz, hash_estimate_size(wee_hash_init_size,
+   sizeof(WaitEventExtensionNameEntry)));
+   sz = add_size(sz, hash_estimate_size(wee_hash_init_size,
+   sizeof(WaitEventExtensionIdEntry)));

Err, this should use the max size, and not the init size for the size
estimation, no?

+   if (strlen(wait_event_name) >= NAMEDATALEN)
+   ereport(ERROR,
+   errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+   errmsg("wait event name is too long"));
This could just be an elog(ERROR), I assume, as that could only be
reached by developers.  The string needs to be rewritten, like "cannot
use custom wait event string longer than %u characters", or something
like that.

+   if (wait_event_info == NULL)
+   {
+   wait_event_info = (uint32 *) MemoryContextAlloc(TopMemoryContext, 
sizeof(uint32));
+   

Re: Support to define custom wait events for extensions

2023-08-09 Thread Andres Freund
Hi,

On 2023-08-09 20:10:42 +0900, Masahiro Ikeda wrote:
> * Is there any way to not force extensions that don't use shared
>   memory for their use like dblink to acquire AddinShmemInitLock?;

I think the caller shouldn't need to do deal with AddinShmemInitLock at all.

Greetings,

Andres Freund




Re: Support to define custom wait events for extensions

2023-08-09 Thread Masahiro Ikeda

Hi,

Thanks for your comments to v1 patch.

I made v2 patch. Main changes are
* change to NAMEDATALEN
* change to use dynahash from dshash
* remove worker_spi_init()
* create second hash table to find a event id from a name to
  identify uniquness. It enable extensions which don't use share
  memory for their use to define custom wait events because
  WaitEventExtensionNew() will not allocate duplicate wait events.
* create PoC patch to show that extensions, which don't use shared
  memory for their use, can define custom wait events.
 (v2-0002-poc-custom-wait-event-for-dblink.patch)

I'm worrying about
* Is 512(wee_hash_max_size) the maximum number of the custom wait
  events sufficient?
* Is there any way to not force extensions that don't use shared
  memory for their use like dblink to acquire AddinShmemInitLock?;

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom ec7d2b0ae47be9bedabb4a4127c914bfb8c361b5 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Wed, 9 Aug 2023 19:19:58 +0900
Subject: [PATCH 1/2] Change to manage custom wait events in shared hash

Currently, names of the custom wait event must be registered
per backends. This patch relaxes the constraints by store the
wait events and their names in hash tables in shared memory.

So, all backends can look up the wait event names on
pg_stat_activity view without additional processing by extensions.

In addition, extensions which do not use shared memory for their
use can define custom wait events because WaitEventExtensionNew()
will never allocate new one if the wait event associated to the
name is already allocated. It use hash table to identify uniquness.
---
 doc/src/sgml/monitoring.sgml  |   7 +-
 doc/src/sgml/xfunc.sgml   |  10 +-
 src/backend/storage/lmgr/lwlocknames.txt  |   1 +
 src/backend/utils/activity/wait_event.c   | 198 +++---
 src/include/utils/wait_event.h|  17 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  18 +-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 -
 src/test/modules/worker_spi/worker_spi.c  |  22 +-
 8 files changed, 137 insertions(+), 141 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f4fc5d814f..19181832d7 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1121,10 +1121,9 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
  LWLock types
  to the list shown in  and
  . In some cases, the name
- assigned by an extension will not be available in all server processes;
- so an Extension or LWLock wait
- event might be reported as just
- extension rather than the
+ of LWLock assigned by an extension will not be
+ available in all server processes; so an wait event might be reported
+ as just extension rather than the
  extension-assigned name.
 

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index d6345a775b..7fec034db4 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3470,17 +3470,13 @@ void RequestAddinShmemSpace(int size)
 
 
 
- shmem_startup_hook can allocate in shared memory
+ shmem_startup_hook can allocate in dynamic shared memory
  custom wait events by calling while holding the LWLock
  AddinShmemInitLock to avoid any race conditions:
 
-uint32 WaitEventExtensionNew(void)
-
- Next, each process needs to associate the wait event allocated previously
- to a user-facing custom string, which is something done by calling:
-
-void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name)
+uint32 WaitEventExtensionNew(const char *wait_event_name)
 
+ The wait event is associated to a user-facing custom string.
  An example can be found in src/test/modules/worker_spi
  in the PostgreSQL source tree.
 
diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt
index b34b6afecd..7af3e0ba1a 100644
--- a/src/backend/storage/lmgr/lwlocknames.txt
+++ b/src/backend/storage/lmgr/lwlocknames.txt
@@ -53,3 +53,4 @@ XactTruncationLock	44
 # 45 was XactTruncationLock until removal of BackendRandomLock
 WrapLimitsVacuumLock46
 NotifyQueueTailLock	47
+WaitEventExtensionLock  48
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index b3596ece80..15b2dd06cc 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -45,6 +45,42 @@ uint32	   *my_wait_event_info = _my_wait_event_info;
 #define WAIT_EVENT_CLASS_MASK	0xFF00
 #define WAIT_EVENT_ID_MASK		0x
 
+/*
+ * Hash tables for storing custom wait event ids and their names in
+ * shared memory.
+ *
+ * WaitEventExtensionNameHash is used to find the name from a event id.
+ * It enables all backends look up them without additional processing
+ * per backend like 

Re: Support to define custom wait events for extensions

2023-08-08 Thread Andres Freund
Hi,

On 2023-08-09 08:03:29 +0900, Michael Paquier wrote:
> On Tue, Aug 08, 2023 at 03:59:54PM -0700, Andres Freund wrote:
> > On 2023-08-08 08:54:10 +0900, Michael Paquier wrote:
> >> - WaitEventExtensionShmemInit() should gain a dshash_create(), to make
> >> sure that the shared table is around, and we are going to have a
> >> reference to it in WaitEventExtensionCounterData, saved from
> >> dshash_get_hash_table_handle().
> > 
> > I'm not even sure it's worth using dshash here. Why don't we just create a
> > decently sized dynahash (say 128 enties) in shared memory? We overallocate
> > shared memory by enough that there's a lot of headroom for further entries, 
> > in
> > the rare cases they're needed.
> 
> The question here would be how many slots the most popular extensions
> actually need, but that could always be sized up based on the
> feedback.

On a default initdb (i.e. 128MB s_b), after explicitly disabling huge pages,
we over-allocate shared memory by by 1922304 bytes, according to
pg_shmem_allocations. We allow that memory to be used for things like shared
hashtables that grow beyond their initial size. So even if the hash table's
static size is too small, there's lots of room to grow, even on small systems.

Just because it's somewhat interesting: With huge pages available and not
disabled, we over-allocate by 3364096 bytes.

Greetings,

Andres Freund




Re: Support to define custom wait events for extensions

2023-08-08 Thread Michael Paquier
On Tue, Aug 08, 2023 at 03:59:54PM -0700, Andres Freund wrote:
> On 2023-08-08 08:54:10 +0900, Michael Paquier wrote:
>> - WaitEventExtensionShmemInit() should gain a dshash_create(), to make
>> sure that the shared table is around, and we are going to have a
>> reference to it in WaitEventExtensionCounterData, saved from
>> dshash_get_hash_table_handle().
> 
> I'm not even sure it's worth using dshash here. Why don't we just create a
> decently sized dynahash (say 128 enties) in shared memory? We overallocate
> shared memory by enough that there's a lot of headroom for further entries, in
> the rare cases they're needed.

The question here would be how many slots the most popular extensions
actually need, but that could always be sized up based on the
feedback.

>> We are going to need a fixed size for these custom strings, but perhaps a
>> hard limit of 256 characters for each entry of the hash table is more than
>> enough for most users?
> 
> I'd just use NAMEDATALEN.

Both suggestions WFM.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-08 Thread Andres Freund
Hi,

On 2023-08-08 08:54:10 +0900, Michael Paquier wrote:
> - WaitEventExtensionShmemInit() should gain a dshash_create(), to make
> sure that the shared table is around, and we are going to have a
> reference to it in WaitEventExtensionCounterData, saved from
> dshash_get_hash_table_handle().

I'm not even sure it's worth using dshash here. Why don't we just create a
decently sized dynahash (say 128 enties) in shared memory? We overallocate
shared memory by enough that there's a lot of headroom for further entries, in
the rare cases they're needed.

> We are going to need a fixed size for these custom strings, but perhaps a
> hard limit of 256 characters for each entry of the hash table is more than
> enough for most users?

I'd just use NAMEDATALEN.

- Andres




Re: Support to define custom wait events for extensions

2023-08-08 Thread Michael Paquier
On Tue, Aug 08, 2023 at 08:40:53PM +0900, Masahiro Ikeda wrote:
> I accidentally attached a patch in one previous email.
> But, you don't need to check it, sorry.
> (v1-0001-Change-to-manage-custom-wait-events-in-shared-hash.patch)

Sure, no worries.  With that in place, the init function in worker_spi
can be removed.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-08 Thread Masahiro Ikeda

I accidentally attached a patch in one previous email.
But, you don't need to check it, sorry.
(v1-0001-Change-to-manage-custom-wait-events-in-shared-hash.patch)

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-08 Thread Masahiro Ikeda

On 2023-08-08 10:05, Michael Paquier wrote:

On Tue, Aug 08, 2023 at 09:39:02AM +0900, Masahiro Ikeda wrote:

I am thinking a bit that we also need another hash where the key
is a custom string. For extensions that have no dependencies
with shared_preload_libraries, I think we need to avoid that
WaitEventExtensionNew() is called repeatedly and a new eventId
is issued each time.

So, is it better to have another hash where the key is
a custom string and uniqueness is identified by it to determine
if a new eventId should be issued?


Yeah, I was also considering if something like that is really
necessary, but I cannot stop worrying about adding more contention to
the hash table lookup each time an extention needs to retrieve an
event ID to use for WaitLatch() or such.  The results of the hash
table lookups could be cached in each backend, still it creates an
extra cost when combined with queries running in parallel on
pg_stat_activity that do the opposite lookup event_id -> event_name.

My suggestion adds more load to AddinShmemInitLock instead.
Hence, I was just thinking about relying on AddinShmemInitLock to
insert new entries in the hash table, only if its shmem state is not
found when calling ShmemInitStruct().  Or perhaps it is just OK to not
care about the impact event_name -> event_id lookup for fresh
connections, and just bite the bullet with two lookup keys instead of
relying on AddinShmemInitLock for the addition of new entries in the
hash table?  Hmm, perhaps you're right with your approach here, at the
end.


For the first idea, I agree that if a lot of new connections come in,
it is easy to leads many conflicts. The only solution I can think of
is to use connection pooling now.

IIUC, the second idea is based on the premise of allocating their shared
memory for each extension. In that case, the cons of the first idea can
be solved because the wait event infos are saved in their shared memory 
and

they don't need call WaitEventExtensionNew() anymore. Is that right?

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 0e3ccc6474bfcc51114d9363b7819b68f37fcad3 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Tue, 8 Aug 2023 19:24:32 +0900
Subject: [PATCH] Change to manage custom wait events in shared hash

Currently, names of the custom wait event must be
registered per backends. This patch relaxes the
constraints to store the wait events and their names
in the dynamic shared hashtable. So, all backends can
look up the wait event names on pg_stat_activity view
without additional processing by extensions.
---
 doc/src/sgml/monitoring.sgml  |   7 +-
 doc/src/sgml/xfunc.sgml   |  10 +-
 src/backend/storage/ipc/ipci.c|   6 +
 src/backend/storage/lmgr/lwlock.c |   2 +
 src/backend/utils/activity/wait_event.c   | 275 --
 src/backend/utils/init/postinit.c |   3 +
 src/include/storage/lwlock.h  |   2 +
 src/include/utils/wait_event.h|  17 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  18 +-
 src/test/modules/worker_spi/worker_spi.c  |   6 +-
 src/tools/pgindent/typedefs.list  |   2 +-
 11 files changed, 216 insertions(+), 132 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f4fc5d814f..19181832d7 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1121,10 +1121,9 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
  LWLock types
  to the list shown in  and
  . In some cases, the name
- assigned by an extension will not be available in all server processes;
- so an Extension or LWLock wait
- event might be reported as just
- extension rather than the
+ of LWLock assigned by an extension will not be
+ available in all server processes; so an wait event might be reported
+ as just extension rather than the
  extension-assigned name.
 

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index d6345a775b..7fec034db4 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3470,17 +3470,13 @@ void RequestAddinShmemSpace(int size)
 
 
 
- shmem_startup_hook can allocate in shared memory
+ shmem_startup_hook can allocate in dynamic shared memory
  custom wait events by calling while holding the LWLock
  AddinShmemInitLock to avoid any race conditions:
 
-uint32 WaitEventExtensionNew(void)
-
- Next, each process needs to associate the wait event allocated previously
- to a user-facing custom string, which is something done by calling:
-
-void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name)
+uint32 WaitEventExtensionNew(const char *wait_event_name)
 
+ The wait event is associated to a user-facing custom string.
  An example can be found in src/test/modules/worker_spi
  in the PostgreSQL source tree.
 

Re: Support to define custom wait events for extensions

2023-08-07 Thread Michael Paquier
On Tue, Aug 08, 2023 at 09:39:02AM +0900, Masahiro Ikeda wrote:
> I am thinking a bit that we also need another hash where the key
> is a custom string. For extensions that have no dependencies
> with shared_preload_libraries, I think we need to avoid that
> WaitEventExtensionNew() is called repeatedly and a new eventId
> is issued each time.
> 
> So, is it better to have another hash where the key is
> a custom string and uniqueness is identified by it to determine
> if a new eventId should be issued?

Yeah, I was also considering if something like that is really
necessary, but I cannot stop worrying about adding more contention to
the hash table lookup each time an extention needs to retrieve an
event ID to use for WaitLatch() or such.  The results of the hash
table lookups could be cached in each backend, still it creates an
extra cost when combined with queries running in parallel on
pg_stat_activity that do the opposite lookup event_id -> event_name.
My suggestion adds more load to AddinShmemInitLock instead.

Hence, I was just thinking about relying on AddinShmemInitLock to
insert new entries in the hash table, only if its shmem state is not
found when calling ShmemInitStruct().  Or perhaps it is just OK to not
care about the impact event_name -> event_id lookup for fresh
connections, and just bite the bullet with two lookup keys instead of
relying on AddinShmemInitLock for the addition of new entries in the
hash table?  Hmm, perhaps you're right with your approach here, at the
end.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-07 Thread Masahiro Ikeda

On 2023-08-08 08:54, Michael Paquier wrote:

On Wed, Aug 02, 2023 at 06:34:15PM +0900, Masahiro Ikeda wrote:

On 2023-08-01 12:23, Andres Freund wrote:
This is why the scheme as implemented doesn't really make sense to 
me.

It'd be
much easier to use if we had a shared hashtable with the identifiers
than
what's been merged now.

In plenty of cases it's not realistic for an extension library to run 
in

each
backend, while still needing to wait for things.


OK, I'll try to make a PoC patch.


Hmm.  There are a few things to take into account here:
- WaitEventExtensionShmemInit() should gain a dshash_create(), to make
sure that the shared table is around, and we are going to have a
reference to it in WaitEventExtensionCounterData, saved from
dshash_get_hash_table_handle().
- The hash table entries could just use nextId as key to look at the
entries, with entries added during WaitEventExtensionNew(), and use as
contents the name of the wait event.  We are going to need a fixed
size for these custom strings, but perhaps a hard limit of 256
characters for each entry of the hash table is more than enough for
most users?
- WaitEventExtensionRegisterName() could be removed, I guess, replaced
by a single WaitEventExtensionNew(), as of:
uint32 WaitEventExtensionNew(const char *event_name);
- GetWaitEventExtensionIdentifier() needs to switch to a lookup of the
shared hash table, based on the eventId.

All that would save from the extra WaitEventExtensionRegisterName()
needed in the backends to keep a track of the names, indeed.


Thank you for pointing the direction of implementation.

I am thinking a bit that we also need another hash where the key
is a custom string. For extensions that have no dependencies
with shared_preload_libraries, I think we need to avoid that 
WaitEventExtensionNew() is called repeatedly and a new eventId

is issued each time.

So, is it better to have another hash where the key is
a custom string and uniqueness is identified by it to determine
if a new eventId should be issued?

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-07 Thread Michael Paquier
On Wed, Aug 02, 2023 at 06:34:15PM +0900, Masahiro Ikeda wrote:
> On 2023-08-01 12:23, Andres Freund wrote:
>> This is why the scheme as implemented doesn't really make sense to me.
>> It'd be
>> much easier to use if we had a shared hashtable with the identifiers
>> than
>> what's been merged now.
>> 
>> In plenty of cases it's not realistic for an extension library to run in
>> each
>> backend, while still needing to wait for things.
> 
> OK, I'll try to make a PoC patch.

Hmm.  There are a few things to take into account here:
- WaitEventExtensionShmemInit() should gain a dshash_create(), to make
sure that the shared table is around, and we are going to have a
reference to it in WaitEventExtensionCounterData, saved from
dshash_get_hash_table_handle().
- The hash table entries could just use nextId as key to look at the
entries, with entries added during WaitEventExtensionNew(), and use as
contents the name of the wait event.  We are going to need a fixed
size for these custom strings, but perhaps a hard limit of 256
characters for each entry of the hash table is more than enough for
most users?
- WaitEventExtensionRegisterName() could be removed, I guess, replaced
by a single WaitEventExtensionNew(), as of:
uint32 WaitEventExtensionNew(const char *event_name);
- GetWaitEventExtensionIdentifier() needs to switch to a lookup of the
shared hash table, based on the eventId.

All that would save from the extra WaitEventExtensionRegisterName()
needed in the backends to keep a track of the names, indeed.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-08-02 Thread Masahiro Ikeda

On 2023-08-01 12:23, Andres Freund wrote:

Hi,

On 2023-08-01 12:14:49 +0900, Michael Paquier wrote:

On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:
> Thanks for committing the main patch.
>
> In my understanding, the rest works are
> * to support WaitEventExtensionMultiple()
> * to replace WAIT_EVENT_EXTENSION to custom wait events
>
> Do someone already works for them? If not, I'll consider
> how to realize them.

Note that postgres_fdw and dblink use WAIT_EVENT_EXTENSION, but have
no dependency to shared_preload_libraries.  Perhaps these could just
use a dynamic handling but that deserves a separate discussion because
of the fact that they'd need shared memory without being able to
request it.  autoprewarm.c is much simpler.


This is why the scheme as implemented doesn't really make sense to me. 
It'd be
much easier to use if we had a shared hashtable with the identifiers 
than

what's been merged now.

In plenty of cases it's not realistic for an extension library to run 
in each

backend, while still needing to wait for things.


OK, I'll try to make a PoC patch.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-01 Thread Ranier Vilela
Em ter., 1 de ago. de 2023 às 21:34, Masahiro Ikeda <
ikeda...@oss.nttdata.com> escreveu:

> On 2023-08-02 08:38, Ranier Vilela wrote:
> > Hi,
> >
> > On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:
> >> Thanks for committing the main patch.
> >
> > Latest head
> > Ubuntu 64 bits
> > gcc 13 64 bits
> >
> > ./configure --without-icu
> > make clean
> >
> > make
> >
> > In file included from ../../src/include/pgstat.h:20,
> >  from controldata_utils.c:38:
> > ../../src/include/utils/wait_event.h:56:9: error: redeclaration of
> > enumerator ‘WAIT_EVENT_EXTENSION’
> >56 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
> >   | ^~~~
> > In file included from ../../src/include/utils/wait_event.h:29,
> >  from ../../src/include/pgstat.h:20,
> >  from controldata_utils.c:38:
> > ../../src/include/utils/wait_event_types.h:60:9: note: previous
> > definition of ‘WAIT_EVENT_EXTENSION’ with type ‘enum
> > ’
> >60 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION
> >   | ^~~~
> > In file included from ../../src/include/pgstat.h:20,
> >  from controldata_utils.c:38:
> > ../../src/include/utils/wait_event.h:58:3: error: conflicting types
> > for ‘WaitEventExtension’; have ‘enum ’
> >58 | } WaitEventExtension;
> >   |   ^~
> > In file included from ../../src/include/utils/wait_event.h:29,
> >  from ../../src/include/pgstat.h:20,
> >  from controldata_utils.c:38:
> > ../../src/include/utils/wait_event_types.h:61:3: note: previous
> > declaration of ‘WaitEventExtension’ with type
> > ‘WaitEventExtension’
> >61 | } WaitEventExtension;
> >   |   ^~
> > make[2]: *** [Makefile:174: controldata_utils_srv.o] Erro 1
> > make[2]: Saindo do diretório '/usr/src/postgres_commits/src/common'
> > make[1]: *** [Makefile:42: all-common-recurse] Erro 2
> > make[1]: Saindo do diretório '/usr/src/postgres_commits/src'
> > make: *** [GNUmakefile:11: all-src-recurse] Erro 2
> > ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
> > "WAIT_EVENT_EXTESION" .
> > ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
> > "WAIT_EVENT_EXTENSION" .
> >
> > grep -r --include '*.h' "WAIT_EVENT_EXTENSION" .
> > ./src/backend/utils/activity/wait_event_types.h: WAIT_EVENT_EXTENSION
> > = PG_WAIT_EXTENSION
> > ./src/include/utils/wait_event.h: WAIT_EVENT_EXTENSION =
> > PG_WAIT_EXTENSION,
> > ./src/include/utils/wait_event.h:
> > WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
> >
> > Not sure if this is really a mistake in my environment.
>
> I can build without error.
> * latest commit(3845577cb55eab3e06b3724e307ebbcac31f4841)
> * gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
>
> The result in my environment is
> $ grep -r --include '*.h' "WAIT_EVENT_EXTENSION" .
> ./src/include/utils/wait_event.h:   WAIT_EVENT_EXTENSION =
> PG_WAIT_EXTENSION,
> ./src/include/utils/wait_event.h:
> WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
>
> I think the error occurred because the old wait_event_types.h still
> exists.
> Can you remove it before building and try again?
>
> $ make maintainer-clean # remove wait_event_types.h
> $ ./configure --without-icu
> $ make
>
Yeah, removing wait_event_types.h works.

Thanks.

regards,
Ranier Vilela


Re: Support to define custom wait events for extensions

2023-08-01 Thread Masahiro Ikeda

On 2023-08-02 08:38, Ranier Vilela wrote:

Hi,

On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:

Thanks for committing the main patch.


Latest head
Ubuntu 64 bits
gcc 13 64 bits

./configure --without-icu
make clean

make

In file included from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event.h:56:9: error: redeclaration of
enumerator ‘WAIT_EVENT_EXTENSION’
   56 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
  | ^~~~
In file included from ../../src/include/utils/wait_event.h:29,
 from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event_types.h:60:9: note: previous
definition of ‘WAIT_EVENT_EXTENSION’ with type ‘enum
’
   60 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION
  | ^~~~
In file included from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event.h:58:3: error: conflicting types
for ‘WaitEventExtension’; have ‘enum ’
   58 | } WaitEventExtension;
  |   ^~
In file included from ../../src/include/utils/wait_event.h:29,
 from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event_types.h:61:3: note: previous
declaration of ‘WaitEventExtension’ with type
‘WaitEventExtension’
   61 | } WaitEventExtension;
  |   ^~
make[2]: *** [Makefile:174: controldata_utils_srv.o] Erro 1
make[2]: Saindo do diretório '/usr/src/postgres_commits/src/common'
make[1]: *** [Makefile:42: all-common-recurse] Erro 2
make[1]: Saindo do diretório '/usr/src/postgres_commits/src'
make: *** [GNUmakefile:11: all-src-recurse] Erro 2
ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
"WAIT_EVENT_EXTESION" .
ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
"WAIT_EVENT_EXTENSION" .

grep -r --include '*.h' "WAIT_EVENT_EXTENSION" .
./src/backend/utils/activity/wait_event_types.h: WAIT_EVENT_EXTENSION
= PG_WAIT_EXTENSION
./src/include/utils/wait_event.h: WAIT_EVENT_EXTENSION =
PG_WAIT_EXTENSION,
./src/include/utils/wait_event.h:
WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED

Not sure if this is really a mistake in my environment.


I can build without error.
* latest commit(3845577cb55eab3e06b3724e307ebbcac31f4841)
* gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)

The result in my environment is
$ grep -r --include '*.h' "WAIT_EVENT_EXTENSION" .
./src/include/utils/wait_event.h:   WAIT_EVENT_EXTENSION = 
PG_WAIT_EXTENSION,
./src/include/utils/wait_event.h:   
WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED


I think the error occurred because the old wait_event_types.h still 
exists.

Can you remove it before building and try again?

$ make maintainer-clean # remove wait_event_types.h
$ ./configure --without-icu
$ make

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-08-01 Thread Ranier Vilela
Hi,

On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:
> Thanks for committing the main patch.

Latest head
Ubuntu 64 bits
gcc 13 64 bits

./configure --without-icu
make clean
make

In file included from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event.h:56:9: error: redeclaration of
enumerator ‘WAIT_EVENT_EXTENSION’
   56 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
  | ^~~~
In file included from ../../src/include/utils/wait_event.h:29,
 from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event_types.h:60:9: note: previous definition
of ‘WAIT_EVENT_EXTENSION’ with type ‘enum ’
   60 | WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION
  | ^~~~
In file included from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event.h:58:3: error: conflicting types for
‘WaitEventExtension’; have ‘enum ’
   58 | } WaitEventExtension;
  |   ^~
In file included from ../../src/include/utils/wait_event.h:29,
 from ../../src/include/pgstat.h:20,
 from controldata_utils.c:38:
../../src/include/utils/wait_event_types.h:61:3: note: previous declaration
of ‘WaitEventExtension’ with type ‘WaitEventExtension’
   61 | } WaitEventExtension;
  |   ^~
make[2]: *** [Makefile:174: controldata_utils_srv.o] Erro 1
make[2]: Saindo do diretório '/usr/src/postgres_commits/src/common'
make[1]: *** [Makefile:42: all-common-recurse] Erro 2
make[1]: Saindo do diretório '/usr/src/postgres_commits/src'
make: *** [GNUmakefile:11: all-src-recurse] Erro 2
ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
"WAIT_EVENT_EXTESION" .
ranier@notebook2:/usr/src/postgres_commits$ grep -r --include '*.c'
"WAIT_EVENT_EXTENSION" .

grep -r --include '*.h' "WAIT_EVENT_EXTENSION" .
./src/backend/utils/activity/wait_event_types.h: WAIT_EVENT_EXTENSION =
PG_WAIT_EXTENSION
./src/include/utils/wait_event.h: WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
./src/include/utils/wait_event.h: WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED

Not sure if this is really a mistake in my environment.

regards,
Ranier Vilela


Re: Support to define custom wait events for extensions

2023-07-31 Thread Andres Freund
Hi,

On 2023-08-01 12:14:49 +0900, Michael Paquier wrote:
> On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:
> > Thanks for committing the main patch.
> > 
> > In my understanding, the rest works are
> > * to support WaitEventExtensionMultiple()
> > * to replace WAIT_EVENT_EXTENSION to custom wait events
> > 
> > Do someone already works for them? If not, I'll consider
> > how to realize them.
> 
> Note that postgres_fdw and dblink use WAIT_EVENT_EXTENSION, but have
> no dependency to shared_preload_libraries.  Perhaps these could just
> use a dynamic handling but that deserves a separate discussion because
> of the fact that they'd need shared memory without being able to
> request it.  autoprewarm.c is much simpler.

This is why the scheme as implemented doesn't really make sense to me. It'd be
much easier to use if we had a shared hashtable with the identifiers than
what's been merged now.

In plenty of cases it's not realistic for an extension library to run in each
backend, while still needing to wait for things.

Greetings,

Andres Freund




Re: Support to define custom wait events for extensions

2023-07-31 Thread Michael Paquier
On Tue, Aug 01, 2023 at 11:51:35AM +0900, Masahiro Ikeda wrote:
> Thanks for committing the main patch.
> 
> In my understanding, the rest works are
> * to support WaitEventExtensionMultiple()
> * to replace WAIT_EVENT_EXTENSION to custom wait events
> 
> Do someone already works for them? If not, I'll consider
> how to realize them.

Note that postgres_fdw and dblink use WAIT_EVENT_EXTENSION, but have
no dependency to shared_preload_libraries.  Perhaps these could just
use a dynamic handling but that deserves a separate discussion because
of the fact that they'd need shared memory without being able to
request it.  autoprewarm.c is much simpler.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-31 Thread Masahiro Ikeda

On 2023-07-31 19:22, Michael Paquier wrote:

I am not sure that any of that is necessary.  Anyway, I have applied
v11 to get the basics done.


Thanks for committing the main patch.

In my understanding, the rest works are
* to support WaitEventExtensionMultiple()
* to replace WAIT_EVENT_EXTENSION to custom wait events

Do someone already works for them? If not, I'll consider
how to realize them.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-31 Thread Bharath Rupireddy
On Mon, Jul 31, 2023 at 3:54 PM Michael Paquier  wrote:
>
> On Mon, Jul 31, 2023 at 05:10:21PM +0900, Kyotaro Horiguchi wrote:
> > +/*
> > + * Return the name of an wait event ID for extension.
> > + */
> > +static const char *
> > +GetWaitEventExtensionIdentifier(uint16 eventId)
> >
> > This looks inconsistent. Shouldn't it be GetWaitEventExtentionName()?
>
> This is an inspiration from GetLWLockIdentifier(), which is kind of OK
> by me.  If there is a consensus in changing that, fine by me, of
> course.

+1 to GetWaitEventExtensionIdentifier for consistency with LWLock's counterpart.

-- 
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-07-31 Thread Michael Paquier
On Mon, Jul 31, 2023 at 05:10:21PM +0900, Kyotaro Horiguchi wrote:
> +/*
> + * Return the name of an wait event ID for extension.
> + */
> +static const char *
> +GetWaitEventExtensionIdentifier(uint16 eventId)
> 
> This looks inconsistent. Shouldn't it be GetWaitEventExtentionName()?

This is an inspiration from GetLWLockIdentifier(), which is kind of OK
by me.  If there is a consensus in changing that, fine by me, of
course.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-31 Thread Michael Paquier
On Mon, Jul 31, 2023 at 01:37:49PM +0530, Bharath Rupireddy wrote:
> Do you think it's worth adding a note here in the docs about an
> external module defining more than one custom wait event? A pseudo
> code if possible or just a note? Also, how about a XXX comment atop
> WaitEventExtensionNew and/or WaitEventExtensionRegisterName on the
> possibility of extending the functions to support allocation of more
> than one custom wait events?

I am not sure that any of that is necessary.  Anyway, I have applied
v11 to get the basics done.

Now, I agree that a WaitEventExtensionMultiple() may come in handy,
particularly for postgres_fdw that uses WAIT_EVENT_EXTENSION three
times.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-31 Thread Kyotaro Horiguchi
At Mon, 31 Jul 2023 16:28:16 +0900, Michael Paquier  wrote 
in 
> Attaching a v11 based on Bharath's feedback and yours, for now.  I
> have also applied the addition of the two masking variables in
> wait_event.c separately with 7395a90.

+/*
+ * Return the name of an wait event ID for extension.
+ */
+static const char *
+GetWaitEventExtensionIdentifier(uint16 eventId)

This looks inconsistent. Shouldn't it be GetWaitEventExtentionName()?

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center




Re: Support to define custom wait events for extensions

2023-07-31 Thread Bharath Rupireddy
On Mon, Jul 31, 2023 at 12:58 PM Michael Paquier  wrote:
>
>
> Attaching a v11 based on Bharath's feedback and yours, for now.  I
> have also applied the addition of the two masking variables in
> wait_event.c separately with 7395a90.

+uint32 WaitEventExtensionNew(void)
+
+ Next, each process needs to associate the wait event allocated previously
+ to a user-facing custom string, which is something done by calling:
+
+void WaitEventExtensionRegisterName(uint32 wait_event_info, const
char *wait_event_name)
+
+ An example can be found in
src/test/modules/worker_spi
+ in the PostgreSQL source tree.
+

Do you think it's worth adding a note here in the docs about an
external module defining more than one custom wait event? A pseudo
code if possible or just a note? Also, how about a XXX comment atop
WaitEventExtensionNew and/or WaitEventExtensionRegisterName on the
possibility of extending the functions to support allocation of more
than one custom wait events?

-- 
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-07-31 Thread Masahiro Ikeda

On 2023-07-31 16:28, Michael Paquier wrote:

On Mon, Jul 31, 2023 at 03:53:27PM +0900, Masahiro Ikeda wrote:

/* This should only be called for user-defined wait event. */
if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid wait event ID %u", eventId));

I was just wondering if it should also check the eventId
that has been allocated though it needs to take the spinlock
and GetWaitEventExtensionIdentifier() doesn't take it into account.


What kind of extra check do you have in mind?  Once WAIT_EVENT_ID_MASK
is applied, we already know that we don't have something larger than
PG_UNIT16_MAX, or perhaps you want to cross-check this number with
what nextId holds in shared memory and that we don't have a number
between nextId and PG_UNIT16_MAX?  I am not sure that we need to care
much about that this much in this code path, and I'd rather avoid
taking an extra time the spinlock just for a cross-check.


OK. I assumed to check that we don't have a number between nextId and
PG_UNIT16_MAX.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-31 Thread Michael Paquier
On Mon, Jul 31, 2023 at 03:53:27PM +0900, Masahiro Ikeda wrote:
> I think the order in which they are mentioned should be matched. I mean that
> - so an LWLock or Extension wait
> + so an Extension or LWLock wait

Makes sense.

>   /* This should only be called for user-defined wait event. */
>   if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
>   ereport(ERROR,
>   errcode(ERRCODE_INVALID_PARAMETER_VALUE),
>   errmsg("invalid wait event ID %u", eventId));
> 
> I was just wondering if it should also check the eventId
> that has been allocated though it needs to take the spinlock
> and GetWaitEventExtensionIdentifier() doesn't take it into account.

What kind of extra check do you have in mind?  Once WAIT_EVENT_ID_MASK
is applied, we already know that we don't have something larger than
PG_UNIT16_MAX, or perhaps you want to cross-check this number with
what nextId holds in shared memory and that we don't have a number
between nextId and PG_UNIT16_MAX?  I am not sure that we need to care
much about that this much in this code path, and I'd rather avoid
taking an extra time the spinlock just for a cross-check.

Attaching a v11 based on Bharath's feedback and yours, for now.  I
have also applied the addition of the two masking variables in
wait_event.c separately with 7395a90.
--
Michael
From 23b6c4c36fbf23ca9c6fb4f42a3f943be44689a6 Mon Sep 17 00:00:00 2001
From: Michael Paquier 
Date: Mon, 31 Jul 2023 16:04:20 +0900
Subject: [PATCH v11] Support custom wait events for wait event type
 "Extension"

Two backend routines are added to allow extension to allocate and define
custom wait events, all of these being allocated as of type "Extension":
* WaitEventExtensionNew(), that allocates a wait event ID computed from
a counter in shared memory.
* WaitEventExtensionRegisterName(), to associate a custom string to the
wait event registered.

Note that this includes an example of how to use this new facility in
worker_spi, with tests for various scenarios.

The use of these routines should be extended across more in-core
modules, but this is left as work for future patches.
---
 src/include/utils/wait_event.h|  26 +++
 src/backend/storage/ipc/ipci.c|   3 +
 .../activity/generate-wait_event_types.pl |   7 +-
 src/backend/utils/activity/wait_event.c   | 178 +-
 .../utils/activity/wait_event_names.txt   |   2 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  34 +++-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 +
 src/test/modules/worker_spi/worker_spi.c  | 104 +-
 doc/src/sgml/monitoring.sgml  |  11 +-
 doc/src/sgml/xfunc.sgml   |  45 +
 src/tools/pgindent/typedefs.list  |   2 +
 11 files changed, 393 insertions(+), 24 deletions(-)

diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index 4517425f84..aad8bc08fa 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -38,6 +38,32 @@ extern void pgstat_reset_wait_event_storage(void);
 extern PGDLLIMPORT uint32 *my_wait_event_info;
 
 
+/* --
+ * Wait Events - Extension
+ *
+ * Use this category when the server process is waiting for some condition
+ * defined by an extension module.
+ *
+ * Extensions can define their own wait events in this category.  First,
+ * they should call WaitEventExtensionNew() to get one or more wait event
+ * IDs that are allocated from a shared counter.  These can be used directly
+ * with pgstat_report_wait_start() or equivalent.  Next, each individual
+ * process should call WaitEventExtensionRegisterName() to associate a wait
+ * event string to the number allocated previously.
+ */
+typedef enum
+{
+	WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
+	WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
+} WaitEventExtension;
+
+extern void WaitEventExtensionShmemInit(void);
+extern Size WaitEventExtensionShmemSize(void);
+
+extern uint32 WaitEventExtensionNew(void);
+extern void WaitEventExtensionRegisterName(uint32 wait_event_info,
+		   const char *wait_event_name);
+
 /* --
  * pgstat_report_wait_start() -
  *
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index cc387c00a1..5551afffc0 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -49,6 +49,7 @@
 #include "storage/spin.h"
 #include "utils/guc.h"
 #include "utils/snapmgr.h"
+#include "utils/wait_event.h"
 
 /* GUCs */
 int			shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
@@ -142,6 +143,7 @@ CalculateShmemSize(int *num_semaphores)
 	size = add_size(size, SyncScanShmemSize());
 	size = add_size(size, AsyncShmemSize());
 	size = add_size(size, StatsShmemSize());
+	size = add_size(size, WaitEventExtensionShmemSize());
 #ifdef EXEC_BACKEND
 	size = add_size(size, ShmemBackendArraySize());
 #endif
@@ -301,6 +303,7 @@ CreateSharedMemoryAndSemaphores(void)
 	

Re: Support to define custom wait events for extensions

2023-07-31 Thread Michael Paquier
On Mon, Jul 31, 2023 at 12:07:40PM +0530, Bharath Rupireddy wrote:
> We're not giving up and returning an unknown state in the v10 patch
> unlike v9, no? This comment needs to change.

Right.  Better to be consistent with lwlock.c here.

>> No, it cannot because we need the custom wait event string to be
>> loaded in the same connection as the one querying pg_stat_activity.
>> A different thing that can be done here is to use background_psql()
>> with a query_until(), though I am not sure that this is worth doing
>> here.
> 
> -1 to go to the background_psql and query_until route. However,
> enhancing the comment might help "we need the custom wait event string
> to be loaded in the same connection as .". Having said this, I
> don't quite understand the point of having worker_spi_init() when we
> say clearly how to use shmem hooks and custom wait events. If its
> intention is to show loading of shared memory to a backend via a
> function, do we really need it in worker_spi? I don't mind removing it
> if it's not adding any significant value.

It seems to initialize the state of the worker_spi, so attaching a
function to this stuff makes sense to me, just for the sake of testing
all that.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-31 Thread Masahiro Ikeda

On 2023-07-31 10:10, Michael Paquier wrote:

Attached is a new version.


Thanks for all the improvements.
I have some comments for v10.

(1)


 
- Extensions can add LWLock types to the list 
shown in
- .  In some cases, the 
name

+ Extensions can add Extension and
+ LWLock types
+ to the list shown in  
and

+ . In some cases, the name
  assigned by an extension will not be available in all server 
processes;

- so an LWLock wait event might be reported as
- just extension rather than the
+ so an LWLock or Extension 
wait

+ event might be reported as just
+ extension rather than the
  extension-assigned name.
 


I think the order in which they are mentioned should be matched. I mean 
that
- so an LWLock or Extension 
wait
+ so an Extension or LWLock 
wait



(2)

/* This should only be called for user-defined wait event. */
if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid wait event ID %u", eventId));

I was just wondering if it should also check the eventId
that has been allocated though it needs to take the spinlock
and GetWaitEventExtensionIdentifier() doesn't take it into account.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-31 Thread Bharath Rupireddy
On Mon, Jul 31, 2023 at 6:40 AM Michael Paquier  wrote:
>
> You are right that I am making things inconsistent here.  Having a
> behavior close to the existing LWLock and use "extension" when the
> event cannot be found makes the most sense.  I have been a bit
> confused with the wording though of this part of the docs, though, as
> LWLocks don't directly use the custom wait event APIs.

+ * calling WaitEventExtensionRegisterName() in the current process, in
+ * which case give up and return an unknown state.

We're not giving up and returning an unknown state in the v10 patch
unlike v9, no? This comment needs to change.

> > 4.
> > + Add-ins can define custom wait events under the wait event type
> >
> > I see a few instances of Add-ins/add-in in xfunc.sgml. Isn't it better
> > to use the word extension given that glossary defines what an
> > extension is 
> > https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-EXTENSION?
>
> An extension is an Add-in, and may be loaded, but it is possible to
> have modules that just need to be LOAD'ed (with command line or just
> shared_preload_libraries) so an add-in may not always be an extension.
> I am not completely sure if add-ins is the best term, but it covers
> both, and that's consistent with the existing docs.  Perhaps the same
> area of the docs should be refreshed, but that looks like a separate
> patch for me.  For now, I'd rather use a consistent term, and this one
> sounds OK to me.
>
> [1]: https://www.postgresql.org/docs/devel/extend-extensions.html.

The "external module" seems the right wording here. Use of "add-ins"
is fine by me for this patch.

> Okay by me that it may be a better idea to use ereport(ERROR) in the
> long run, so changed this way.  I have introduced a
> WAIT_EVENT_CLASS_MASK and a WAIT_EVENT_ID_MASK as we now use
> 0xFF00 and 0x in three places of this file.  This should
> just be a patch on its own.

Yeah, I don't mind these macros going along or before or after the
custom wait events feature.

> Yes, this was mentioned upthread.  I am not completely sure yet how
> much we need to do for this interface, but surely it would be faster
> to have a Multiple() interface that returns an array made of N numbers
> requested (rather than a rank of them).  For now, I'd rather just aim
> for simplicity for the basics.

+1 to be simple for now. If any such requests come in future, I'm sure
we can always get back to it.

> > 9.
> > # The expected result is a special pattern here with a newline coming from 
> > the
> > # first query where the shared memory state is set.
> > $result = $node->poll_query_until(
> > 'postgres',
> > qq[SELECT worker_spi_init(); SELECT wait_event FROM
> > pg_stat_activity WHERE backend_type ~ 'worker_spi';],
> > qq[
> > worker_spi_main]);
> >
> > This test doesn't have to be that complex with the result being a
> > special pattern, SELECT worker_spi_init(); can just be within a
> > separate safe_psql.
>
> No, it cannot because we need the custom wait event string to be
> loaded in the same connection as the one querying pg_stat_activity.
> A different thing that can be done here is to use background_psql()
> with a query_until(), though I am not sure that this is worth doing
> here.

-1 to go to the background_psql and query_until route. However,
enhancing the comment might help "we need the custom wait event string
to be loaded in the same connection as .". Having said this, I
don't quite understand the point of having worker_spi_init() when we
say clearly how to use shmem hooks and custom wait events. If its
intention is to show loading of shared memory to a backend via a
function, do we really need it in worker_spi? I don't mind removing it
if it's not adding any significant value.

-- 
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-07-30 Thread Michael Paquier
On Fri, Jul 28, 2023 at 12:43:36PM +0530, Bharath Rupireddy wrote:
> 1.
> - so an LWLock wait event might be reported as
> - just extension rather than the
> - extension-assigned name.
> + if the extension's library is not loaded; so a custom wait event might
> + be reported as just ???
> + rather than the custom name assigned.
> 
> Trying to understand why '???' is any better than 'extension' for a
> registered custom wait event of an unloaded extension?
> 
> PS: Looked at other instances where '???' is being used for
> representing an unknown "thing".

You are right that I am making things inconsistent here.  Having a
behavior close to the existing LWLock and use "extension" when the
event cannot be found makes the most sense.  I have been a bit
confused with the wording though of this part of the docs, though, as
LWLocks don't directly use the custom wait event APIs.

> 2. Have an example of how a custom wait event is displayed in the
> example in the docs "Here is an example of how wait events can be
> viewed:". We can use the worker_spi wait event type there.

Fine by me, added one.

> 3.
> - so an LWLock wait event might be reported as
> - just extension rather than the
> - extension-assigned name.
> 
> + . In some cases, the name
> + assigned by an extension will not be available in all server processes
> + if the extension's library is not loaded; so a custom wait event might
> + be reported as just ???
> 
> Are we missing to explicitly say what wait event will be reported for
> an LWLock when the extension library is not loaded?

Yes, see answer to point 1.

> 4.
> + Add-ins can define custom wait events under the wait event type
> 
> I see a few instances of Add-ins/add-in in xfunc.sgml. Isn't it better
> to use the word extension given that glossary defines what an
> extension is 
> https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-EXTENSION?

An extension is an Add-in, and may be loaded, but it is possible to
have modules that just need to be LOAD'ed (with command line or just
shared_preload_libraries) so an add-in may not always be an extension.
I am not completely sure if add-ins is the best term, but it covers
both, and that's consistent with the existing docs.  Perhaps the same
area of the docs should be refreshed, but that looks like a separate
patch for me.  For now, I'd rather use a consistent term, and this one
sounds OK to me.

[1]: https://www.postgresql.org/docs/devel/extend-extensions.html.

> 5.
> +} WaitEventExtensionCounter;
> +
> +/* pointer to the shared memory */
> +static WaitEventExtensionCounter *waitEventExtensionCounter;
> 
> How about naming the structure variable as
> WaitEventExtensionCounterData and pointer as
> WaitEventExtensionCounter? This keeps all the static variable names
> consistent WaitEventExtensionNames, WaitEventExtensionNamesAllocated
> and WaitEventExtensionCounter.

Hmm, good point on consistency here, especially to use an upper-case
character for the first characters of waitEventExtensionCounter..
Err..  WaitEventExtensionCounter.

> 6.
> +/* Check the wait event class. */
> +Assert((wait_event_info & 0xFF00) == PG_WAIT_EXTENSION);
> +
> +/* This should only be called for user-defined wait event. */
> +Assert(eventId >= NUM_BUILTIN_WAIT_EVENT_EXTENSION);
> 
> Maybe, we must turn the above asserts into ereport(ERROR) to protect
> against an extension sending in an unregistered wait_event_info?
> Especially, the first Assert((wait_event_info & 0xFF00) ==
> PG_WAIT_EXTENSION); checks that the passed in wait_event_info is
> previously returned by WaitEventExtensionNew. IMO, these assertions
> better fit for errors.

Okay by me that it may be a better idea to use ereport(ERROR) in the
long run, so changed this way.  I have introduced a
WAIT_EVENT_CLASS_MASK and a WAIT_EVENT_ID_MASK as we now use
0xFF00 and 0x in three places of this file.  This should
just be a patch on its own.

> 7.
> + * Extensions can define their own wait events in this categiry.  First,
> Typo - s/categiry/category

Thanks, missed that.

> 8.
> + First,
> + * they should call WaitEventExtensionNew() to get one or more wait event
> + * IDs that are allocated from a shared counter.
> 
> Can WaitEventExtensionNew() be WaitEventExtensionNew(int num_ids, int
> *result) to get the required number of wait event IDs in one call
> similar to RequestNamedLWLockTranche? Currently, an extension needs to
> call WaitEventExtensionNew() N number of times to get N wait event
> IDs. Maybe the existing WaitEventExtensionNew() is good, but just a
> thought.

Yes, this was mentioned upthread.  I am not completely sure yet how
much we need to do for this interface, but surely it would be faster
to have a Multiple() interface that returns an array made of N numbers
requested (rather than a rank of them).  For now, I'd rather just aim
for simplicity for the basics.

> 9.
> # The expected result is a 

Re: Support to define custom wait events for extensions

2023-07-28 Thread Bharath Rupireddy
On Fri, Jul 28, 2023 at 6:36 AM Michael Paquier  wrote:
>
> I have spent more time polishing the docs and the comments.  This v9
> looks in a rather committable shape now with docs, tests and core
> routines in place.

Thanks. Here are some comments on v9 patch:

1.
- so an LWLock wait event might be reported as
- just extension rather than the
- extension-assigned name.
+ if the extension's library is not loaded; so a custom wait event might
+ be reported as just ???
+ rather than the custom name assigned.

Trying to understand why '???' is any better than 'extension' for a
registered custom wait event of an unloaded extension?

PS: Looked at other instances where '???' is being used for
representing an unknown "thing".

2. Have an example of how a custom wait event is displayed in the
example in the docs "Here is an example of how wait events can be
viewed:". We can use the worker_spi wait event type there.

3.
- so an LWLock wait event might be reported as
- just extension rather than the
- extension-assigned name.

+ . In some cases, the name
+ assigned by an extension will not be available in all server processes
+ if the extension's library is not loaded; so a custom wait event might
+ be reported as just ???

Are we missing to explicitly say what wait event will be reported for
an LWLock when the extension library is not loaded?

4.
+ Add-ins can define custom wait events under the wait event type

I see a few instances of Add-ins/add-in in xfunc.sgml. Isn't it better
to use the word extension given that glossary defines what an
extension is 
https://www.postgresql.org/docs/current/glossary.html#GLOSSARY-EXTENSION?

5.
+} WaitEventExtensionCounter;
+
+/* pointer to the shared memory */
+static WaitEventExtensionCounter *waitEventExtensionCounter;

How about naming the structure variable as
WaitEventExtensionCounterData and pointer as
WaitEventExtensionCounter? This keeps all the static variable names
consistent WaitEventExtensionNames, WaitEventExtensionNamesAllocated
and WaitEventExtensionCounter.

6.
+/* Check the wait event class. */
+Assert((wait_event_info & 0xFF00) == PG_WAIT_EXTENSION);
+
+/* This should only be called for user-defined wait event. */
+Assert(eventId >= NUM_BUILTIN_WAIT_EVENT_EXTENSION);

Maybe, we must turn the above asserts into ereport(ERROR) to protect
against an extension sending in an unregistered wait_event_info?
Especially, the first Assert((wait_event_info & 0xFF00) ==
PG_WAIT_EXTENSION); checks that the passed in wait_event_info is
previously returned by WaitEventExtensionNew. IMO, these assertions
better fit for errors.

7.
+ * Extensions can define their own wait events in this categiry.  First,
Typo - s/categiry/category

8.
+ First,
+ * they should call WaitEventExtensionNew() to get one or more wait event
+ * IDs that are allocated from a shared counter.

Can WaitEventExtensionNew() be WaitEventExtensionNew(int num_ids, int
*result) to get the required number of wait event IDs in one call
similar to RequestNamedLWLockTranche? Currently, an extension needs to
call WaitEventExtensionNew() N number of times to get N wait event
IDs. Maybe the existing WaitEventExtensionNew() is good, but just a
thought.

9.
# The expected result is a special pattern here with a newline coming from the
# first query where the shared memory state is set.
$result = $node->poll_query_until(
'postgres',
qq[SELECT worker_spi_init(); SELECT wait_event FROM
pg_stat_activity WHERE backend_type ~ 'worker_spi';],
qq[
worker_spi_main]);

This test doesn't have to be that complex with the result being a
special pattern, SELECT worker_spi_init(); can just be within a
separate safe_psql.

10.
+wsstate = ShmemInitStruct("custom_wait_event",

Name the shared memory just "worker_spi" to make it generic and
extensible. Essentially, it is a woker_spi shared memory area part of
it is for custom wait event id.

--
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-07-27 Thread Michael Paquier
On Thu, Jul 27, 2023 at 06:29:22PM +0900, Masahiro Ikeda wrote:
> I suspect that I forgot to specify "volatile" to the variable
> for the spinlock.

+   if (!IsUnderPostmaster)
+   {
+   /* Allocate space in shared memory. */
+   waitEventExtensionCounter = (WaitEventExtensionCounter *)
+   ShmemInitStruct("waitEventExtensionCounter", 
WaitEventExtensionShmemSize(), );
+   if (found)
+   return;

I think that your error is here.  WaitEventExtensionShmemInit() is
forgetting to set the pointer to waitEventExtensionCounter for
processes where IsUnderPostmaster is true, which impacts things not
forked like in -DEXEC_BACKEND (the crash is reproducible on Linux with
-DEXEC_BACKEND in CFLAGS, as well).  The correct thing to do is to
always call ShmemInitStruct, but only initialize the contents of the
shared memory area if ShmemInitStruct() has *not* found the shmem
contents.

WaitEventExtensionNew() could be easily incorrectly used, so I'd
rather add a LWLockHeldByMeInMode() on AddinShmemInitLock as safety
measure.  Perhaps we should do the same for the LWLocks, subject for a
different thread..

+   int newalloc;
+
+   newalloc = pg_nextpower2_32(Max(8, eventId + 1));

This should be a uint32.

+   if (eventId >= WaitEventExtensionNamesAllocated ||
+   WaitEventExtensionNames[eventId] == NULL)
+   return "extension";
That's too close to the default of "Extension".  It would be cleaner
to use "unknown", but we've been using "???" as well in many default
paths where an ID cannot be mapped to a string, so I would recommend
to just use that.

I have spent more time polishing the docs and the comments.  This v9
looks in a rather committable shape now with docs, tests and core
routines in place.
--
Michael
From 766d1db13035eefd87a02adb88853f575abe75cb Mon Sep 17 00:00:00 2001
From: Michael Paquier 
Date: Fri, 28 Jul 2023 10:01:43 +0900
Subject: [PATCH v9] Support custom wait events for wait event type "Extension"

Two backend routines are added to allow extension to allocate and define
custom wait events, all of these being allocated as of type "Extension":
* WaitEventExtensionNew(), that allocates a wait event ID computed from
a counter in shared memory.
* WaitEventExtensionRegisterName(), to associate a custom string to the
wait event registered.

Note that this includes an example of how to use this new facility in
worker_spi, with tests for various scenarios.

The use of these routines should be extended across more in-core
modules, but this is left as work for future patches.
---
 src/include/utils/wait_event.h|  26 +++
 src/backend/storage/ipc/ipci.c|   3 +
 .../activity/generate-wait_event_types.pl |   7 +-
 src/backend/utils/activity/wait_event.c   | 171 +-
 .../utils/activity/wait_event_names.txt   |   2 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  31 +++-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 +
 src/test/modules/worker_spi/worker_spi.c  | 104 ++-
 doc/src/sgml/monitoring.sgml  |  13 +-
 doc/src/sgml/xfunc.sgml   |  33 
 10 files changed, 369 insertions(+), 26 deletions(-)

diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index 4517425f84..3e38215c2d 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -38,6 +38,32 @@ extern void pgstat_reset_wait_event_storage(void);
 extern PGDLLIMPORT uint32 *my_wait_event_info;
 
 
+/* --
+ * Wait Events - Extension
+ *
+ * Use this category when the server process is waiting for some condition
+ * defined by an extension module.
+ *
+ * Extensions can define their own wait events in this categiry.  First,
+ * they should call WaitEventExtensionNew() to get one or more wait event
+ * IDs that are allocated from a shared counter.  These can be used directly
+ * with pgstat_report_wait_start() or equivalent.  Next, each individual
+ * process should call WaitEventExtensionRegisterName() to associate a wait
+ * event string to the number allocated previously.
+ */
+typedef enum
+{
+	WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
+	WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
+} WaitEventExtension;
+
+extern void WaitEventExtensionShmemInit(void);
+extern Size WaitEventExtensionShmemSize(void);
+
+extern uint32 WaitEventExtensionNew(void);
+extern void WaitEventExtensionRegisterName(uint32 wait_event_info,
+		   const char *wait_event_name);
+
 /* --
  * pgstat_report_wait_start() -
  *
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index cc387c00a1..5551afffc0 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -49,6 +49,7 @@
 #include "storage/spin.h"
 #include "utils/guc.h"
 #include "utils/snapmgr.h"
+#include "utils/wait_event.h"
 
 /* GUCs */
 int			shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
@@ -142,6 +143,7 @@ CalculateShmemSize(int 

Re: Support to define custom wait events for extensions

2023-07-27 Thread Masahiro Ikeda

Hi, all.

Sorry for late reply.


I am still mid-way through the review of the core APIs, but attached
is my current version in progress, labelled v8.  I'll continue
tomorrow.  I'm aware of some typos in the commit message of this
patch, and the dynamic bgworker launch is failing in the CI for
VS2019 (just too tired to finish debugging that today).


I suspect that I forgot to specify "volatile" to the variable
for the spinlock.

+/* dynamic allocation counter for custom wait events for extensions */
+typedef struct WaitEventExtensionCounter
+{
+   int nextId; /* next ID to assign */
+   slock_t mutex;  /* protects the counter only */
+}  WaitEventExtensionCounter;
+
+/* pointer to the shared memory */
+static WaitEventExtensionCounter * waitEventExtensionCounter;

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-27 Thread Michael Paquier
On Wed, Jul 19, 2023 at 10:57:39AM -0500, Tristan Partin wrote:
> > +   
> > +Custom Wait Events for Add-ins
> 
> This would be the second use of "Add-ins" ever, according to my search.
> Should this be "Extensions" instead?

Yes, I would think that just "Custom Wait Events" is enough here.
And I'd recommend to also use Shared Memory here.  The case of
dynamically loaded things is possible, more advanced and can work, but
I am not sure we really need to do down to that as long as we mention
to use shared_preload_libraries.

I've rewritten the docs in their entirety, but honestly I still need
to spend more time polishing that.

Another part of the patch that has been itching me a lot are the
regression tests.  I have spent some time today migrating the tests of
worker_spi to TAP for the sake of this thread, resulting in commit
320c311, and concluded that we need to care about three new cases:
- For custom wait events where the shmem state is not loaded, check
that we report the default of 'extension'.
- Check that it is possible to allocate and load a custom wait event
dynamically.  Here, I have used a new SQL function in worker_spi,
called worker_spi_init().  That feels a bit hack-ish but for a test in
a template module that works great.
- Check that wait events loaded through shared_preload_libraries work
correctly.

The tests of worker_spi can take care easily of all these cases, once
a few things for the shmem handling are put in place for the dynamic
and preloading cases.

+Datum
+get_new_wait_event_info(PG_FUNCTION_ARGS)
+{
+   PG_RETURN_UINT32(WaitEventExtensionNew());
+}

While looking at the previous patch and the test, I've noticed this
pattern.  WaitEventExtensionNew() should not be called without holding
AddinShmemInitLock, or that opens the door to race conditions.

I am still mid-way through the review of the core APIs, but attached
is my current version in progress, labelled v8.  I'll continue
tomorrow.  I'm aware of some typos in the commit message of this
patch, and the dynamic bgworker launch is failing in the CI for
VS2019 (just too tired to finish debugging that today).

Thoughts are welcome.
--
Michael
From deb7cab66671e0277cc34236c7515f4ea18fac65 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Wed, 19 Jul 2023 12:28:12 +0900
Subject: [PATCH v8] Support custom wait events for extensions.

To support custom wait events, it add 2 APIs to define new wait events
for extensions dynamically.

The APIs are
* WaitEventExtensionNew()
* WaitEventExtensionRegisterName()

These are similar to the existing LWLockNewTrancheId() and
LWLockRegisterTranche().

First, extensions should call WaitEventExtensionNew() to get one
or more new wait event, which IDs are allocated from a shared
counter.  Next, each individual process can use the wait event with
WaitEventExtensionRegisterName() to associate that a wait event
string to the associated name.

Note that this includes an example of how to use this new facility in
worker_spi.
---
 src/include/utils/wait_event.h|  25 +++
 src/backend/storage/ipc/ipci.c|   3 +
 .../activity/generate-wait_event_types.pl |   7 +-
 src/backend/utils/activity/wait_event.c   | 171 +-
 .../utils/activity/wait_event_names.txt   |   2 +-
 .../modules/worker_spi/t/001_worker_spi.pl|  31 +++-
 .../modules/worker_spi/worker_spi--1.0.sql|   5 +
 src/test/modules/worker_spi/worker_spi.c  | 105 ++-
 doc/src/sgml/monitoring.sgml  |  13 +-
 doc/src/sgml/xfunc.sgml   |  34 
 10 files changed, 370 insertions(+), 26 deletions(-)

diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index 4517425f84..d405398b75 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -67,6 +67,31 @@ pgstat_report_wait_start(uint32 wait_event_info)
 	*(volatile uint32 *) my_wait_event_info = wait_event_info;
 }
 
+/* --
+ * Wait Events - Extension
+ *
+ * Use this category when the server process is waiting for some condition
+ * defined by an extension module.
+ *
+ * Extensions can define their wait events. First, extensions should call
+ * WaitEventExtensionNew() to get one or more wait events, which IDs are
+ * allocated from a shared counter.  Next, each individual process can use
+ * them with WaitEventExtensionRegisterName() to associate that a wait
+ * event string to the associated name.
+ */
+typedef enum
+{
+	WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
+	WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
+} WaitEventExtension;
+
+extern void WaitEventExtensionShmemInit(void);
+extern Size WaitEventExtensionShmemSize(void);
+
+extern uint32 WaitEventExtensionNew(void);
+extern void WaitEventExtensionRegisterName(uint32 wait_event_info,
+		   const char *wait_event_name);
+
 /* --
  * pgstat_report_wait_end() -
  *
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 

Re: Support to define custom wait events for extensions

2023-07-19 Thread Michael Paquier
On Wed, Jul 19, 2023 at 11:16:34AM -0500, Tristan Partin wrote:
> On Tue Jul 11, 2023 at 6:29 PM CDT, Michael Paquier wrote:
>> This style comes from LWLockRegisterTranche() in lwlock.c.  Do you
>> think that it would be more adapted to change that to
>> pg_nextpower2_size_t() with a Size?  We could do that for the existing
>> code on HEAD as an improvement.
> 
> Yes, I think that would be the most correct code. At the very least,
> using a uint32 instead of an int, would be preferrable.

Would you like to send a patch on a new thread about that?

>> Hmm, okay, that would nice to hear about to make sure that the
>> approach taken on this thread is able to cover what you are looking
>> for.  So you mean that Neon has been using something similar to
>> register wait events in the backend?  Last time I looked at the Neon
>> repo, I did not get the impression that there was a custom patch for
>> Postgres in this area.  All the in-core code paths using
>> WAIT_EVENT_EXTENSION would gain from the APIs added here, FWIW.
> 
> I did some investigation into the Neon fork[0], and couldn't find any
> commits that seemed related. Perhaps this is on our wishlist instead of
> something we already have implemented. I have CCed Heikki to talk some
> more about how this would fit in at Neon.
> 
> [0]: https://github.com/neondatabase/postgres

Anybody with complex out-of-core extensions have wanted more
monitoring capabilities for wait events without relying on the core
backend.  To be honest, I would not be surprised to see this stuff on
more than one wishlist.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-19 Thread Tristan Partin

On Tue Jul 11, 2023 at 6:29 PM CDT, Michael Paquier wrote:

On Tue, Jul 11, 2023 at 12:39:52PM -0500, Tristan Partin wrote:
> Given the context of our last conversation, I assume this code was
> copied from somewhere else. Since this is new code, I think it would
> make more sense if newalloc was a uint16 or size_t.

This style comes from LWLockRegisterTranche() in lwlock.c.  Do you
think that it would be more adapted to change that to
pg_nextpower2_size_t() with a Size?  We could do that for the existing
code on HEAD as an improvement.


Yes, I think that would be the most correct code. At the very least,
using a uint32 instead of an int, would be preferrable.


> From what I understand, Neon differs from upstream in some way related
> to this patch. I am trying to ascertain how that is. I hope to provide
> more feedback when I learn more about it.

Hmm, okay, that would nice to hear about to make sure that the
approach taken on this thread is able to cover what you are looking
for.  So you mean that Neon has been using something similar to
register wait events in the backend?  Last time I looked at the Neon
repo, I did not get the impression that there was a custom patch for
Postgres in this area.  All the in-core code paths using
WAIT_EVENT_EXTENSION would gain from the APIs added here, FWIW.


I did some investigation into the Neon fork[0], and couldn't find any
commits that seemed related. Perhaps this is on our wishlist instead of
something we already have implemented. I have CCed Heikki to talk some
more about how this would fit in at Neon.

[0]: https://github.com/neondatabase/postgres

--
Tristan Partin
Neon (https://neon.tech)




Re: Support to define custom wait events for extensions

2023-07-19 Thread Tristan Partin

Thanks for continuing to work on this patchset. I only have
prose-related comments.


To support custom wait events, it add 2 APIs to define new wait events
for extensions dynamically.


Remove the "it" here.


The APIs are
* WaitEventExtensionNew()
* WaitEventExtensionRegisterName()



These are similar to the existing LWLockNewTrancheId() and
LWLockRegisterTranche().


This sentence seems like it could be removed given the API names have
changed during the development of this patch.


First, extensions should call WaitEventExtensionNew() to get one
or more new wait event, which IDs are allocated from a shared
counter.  Next, each individual process can use the wait event with
WaitEventExtensionRegisterName() to associate that a wait event
string to the associated name.


This portion of the commit message is a copy-paste of the function
comment. Whatever you do in the function comment (which I commented on
below), just do here as well.


+ so an wait event might be reported as just 
extension
+ rather than the extension-assigned name.


s/an/a


+   
+Custom Wait Events for Add-ins


This would be the second use of "Add-ins" ever, according to my search.
Should this be "Extensions" instead?


+
+Add-ins can define custom wait events that the wait event type is


s/that/where


+Extension.
+
+
+First, add-ins should get new one or more wait events by calling:


"one or more" doesn't seem to make sense grammatically here.


+
+uint32 WaitEventExtensionNew(void)
+
+Next, each individual process can use them to associate that


Remove "that".


+a wait event string to the associated name by calling:
+
+void WaitEventExtensionRegisterName(uint32 wait_event_info, const char 
*wait_event_name);
+
+An example can be found in
+
src/test/modules/test_custom_wait_events/test_custom_wait_events.c
+in the PostgreSQL source tree.
+
+   



+ * Register a dynamic wait event name for extension in the lookup table
+ * of the current process.


Inserting an "an" before "extension" would make this read better.


+/*
+ * Return the name of an wait event ID for extension.
+ */


s/an/a


+   /*
+* It's an user-defined wait event, so look in 
WaitEventExtensionNames[].
+* However, it's possible that the name has never been registered by
+* calling WaitEventExtensionRegisterName() in the current process, in
+* which case give up and return "extension".
+*/


s/an/a

"extension" seems very similar to "Extension". Instead of returning a
string here, could we just error? This seems like a programmer error on
the part of the extension author.


+ * Extensions can define their wait events. First, extensions should call
+ * WaitEventExtensionNew() to get one or more wait events, which IDs are
+ * allocated from a shared counter.  Next, each individual process can use
+ * them with WaitEventExtensionRegisterName() to associate that a wait
+ * event string to the associated name.


An "own" before "wait events" in the first sentence would increase
clarity. "where" instead of "which" in the next sentence. Remove "that"
after "associate" in the third sentence.

--
Tristan Partin
Neon (https://neon.tech)




Re: Support to define custom wait events for extensions

2023-07-19 Thread Bharath Rupireddy
On Wed, Jul 19, 2023 at 11:49 AM Masahiro Ikeda
 wrote:
>
> I updated the patch since the cfbot found a bug.
> * v7-0001-Support-custom-wait-events-for-extensions.patch

Thanks for working on this feature. +1. I've wanted this capability
for a while because extensions have many different wait loops for
different reasons, a single wait event type isn't enough.

I think we don't need a separate test extension for demonstrating use
of custom wait events, you can leverage the sample extension
worker_spi because that's where extension authors look for while
writing a new extension. Also, it simplifies your patch a lot. I don't
mind adding a few things to worker_spi for the sake of demonstrating
the use and testing for custom wait events.

--
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-07-19 Thread Michael Paquier
On Wed, Jul 19, 2023 at 12:52:10PM +0900, Masahiro Ikeda wrote:
> I would like to change the wait event name of contrib modules for example
> postgres_fdw. But, I think it's better to do so after the APIs are
> committed.

Agreed to do things one step at a time here.  Let's focus on the core
APIs and facilities first.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-19 Thread Masahiro Ikeda

On 2023-07-19 12:52, Masahiro Ikeda wrote:

Hi,

I updated the patches.
* v6-0001-Support-custom-wait-events-for-extensions.patch


I updated the patch since the cfbot found a bug.
* v7-0001-Support-custom-wait-events-for-extensions.patch

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom e5d63913cbba9f20098252cc1e415eda4d32f5ad Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Wed, 19 Jul 2023 12:28:12 +0900
Subject: [PATCH] Support custom wait events for extensions.

To support custom wait events, it add 2 APIs to define new wait events
for extensions dynamically.

The APIs are
* WaitEventExtensionNew()
* WaitEventExtensionRegisterName()

These are similar to the existing LWLockNewTrancheId() and
LWLockRegisterTranche().

First, extensions should call WaitEventExtensionNew() to get one
or more new wait event, which IDs are allocated from a shared
counter.  Next, each individual process can use the wait event with
WaitEventExtensionRegisterName() to associate that a wait event
string to the associated name.

Note that this includes a test module, which perhaps should be split
later into its own commit.
---
 doc/src/sgml/monitoring.sgml  |  10 +-
 doc/src/sgml/xfunc.sgml   |  23 ++
 src/backend/storage/ipc/ipci.c|   3 +
 .../activity/generate-wait_event_types.pl |   7 +-
 src/backend/utils/activity/wait_event.c   | 171 +++-
 .../utils/activity/wait_event_names.txt   |   2 +-
 src/include/utils/wait_event.h|  25 ++
 src/test/modules/Makefile |   1 +
 src/test/modules/meson.build  |   1 +
 .../test_custom_wait_events/.gitignore|   4 +
 .../modules/test_custom_wait_events/Makefile  |  23 ++
 .../test_custom_wait_events/meson.build   |  33 +++
 .../test_custom_wait_events/t/001_basic.pl| 137 ++
 .../test_custom_wait_events--1.0.sql  |  39 +++
 .../test_custom_wait_events.c | 253 ++
 .../test_custom_wait_events.control   |   3 +
 16 files changed, 718 insertions(+), 17 deletions(-)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 588b720f57..3aee5c243f 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1117,12 +1117,12 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 

 
- Extensions can add LWLock types to the list shown in
- .  In some cases, the name
+ Extensions can add Extension and LWLock types
+ to the list shown in  and
+ . In some cases, the name
  assigned by an extension will not be available in all server processes;
- so an LWLock wait event might be reported as
- just extension rather than the
- extension-assigned name.
+ so an wait event might be reported as just extension
+ rather than the extension-assigned name.
 

  
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 9620ea9ae3..bc210cd03b 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3453,6 +3453,29 @@ if (!ptr)
 

 
+   
+Custom Wait Events for Add-ins
+
+
+Add-ins can define custom wait events that the wait event type is
+Extension.
+
+
+First, add-ins should get new one or more wait events by calling:
+
+uint32 WaitEventExtensionNew(void)
+
+Next, each individual process can use them to associate that
+a wait event string to the associated name by calling:
+
+void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name);
+
+An example can be found in
+src/test/modules/test_custom_wait_events/test_custom_wait_events.c
+in the PostgreSQL source tree.
+
+   
+

 Using C++ for Extensibility
 
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index cc387c00a1..5551afffc0 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -49,6 +49,7 @@
 #include "storage/spin.h"
 #include "utils/guc.h"
 #include "utils/snapmgr.h"
+#include "utils/wait_event.h"
 
 /* GUCs */
 int			shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
@@ -142,6 +143,7 @@ CalculateShmemSize(int *num_semaphores)
 	size = add_size(size, SyncScanShmemSize());
 	size = add_size(size, AsyncShmemSize());
 	size = add_size(size, StatsShmemSize());
+	size = add_size(size, 

Re: Support to define custom wait events for extensions

2023-07-18 Thread Masahiro Ikeda

Hi,

I updated the patches.
* v6-0001-Support-custom-wait-events-for-extensions.patch

The main diffs are

* rebase it atop current HEAD
* update docs to show users how to use the APIs
* rename of functions and variables
* fix typos
* define a new spinlock in shared memory for this purpose
* output an error if the number of wait event for extensions exceeds 
uint16
* show the wait event as "extension" if the custom wait event name is 
not

  registered, which is same as LWLock one.
* add test cases which confirm it works if new wait events for 
extensions

  are defined in initialize phase and after phase. And add a boundary
  condition test.

Please let me know if I forgot to handle something that you commented,
and there are better idea.

Note:
I would like to change the wait event name of contrib modules for 
example
postgres_fdw. But, I think it's better to do so after the APIs are 
committed.
The example mentioned in docs should be updated to the contrib modules 
codes,

not the test module.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 9c5c1f1f4f0be87cc06c7127396e7d228b665b8a Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Wed, 19 Jul 2023 12:28:12 +0900
Subject: [PATCH] Support custom wait events for extensions.

To support custom wait events, it add 2 APIs to define new wait events
for extensions dynamically.

The APIs are
* WaitEventExtensionNew()
* WaitEventExtensionRegisterName()

These are similar to the existing LWLockNewTrancheId() and
LWLockRegisterTranche().

First, extensions should call WaitEventExtensionNew() to get one
or more new wait event, which IDs are allocated from a shared
counter.  Next, each individual process can use the wait event with
WaitEventExtensionRegisterName() to associate that a wait event
string to the associated name.

Note that this includes a test module, which perhaps should be split
later into its own commit.
---
 doc/src/sgml/monitoring.sgml  |  10 +-
 doc/src/sgml/xfunc.sgml   |  23 ++
 src/backend/storage/ipc/ipci.c|   3 +
 .../activity/generate-wait_event_types.pl |   7 +-
 src/backend/utils/activity/wait_event.c   | 171 +++-
 .../utils/activity/wait_event_names.txt   |   2 +-
 src/include/utils/wait_event.h|  25 ++
 src/test/modules/Makefile |   1 +
 src/test/modules/meson.build  |   1 +
 .../test_custom_wait_events/.gitignore|   4 +
 .../modules/test_custom_wait_events/Makefile  |  23 ++
 .../test_custom_wait_events/meson.build   |  33 +++
 .../test_custom_wait_events/t/001_basic.pl| 137 ++
 .../test_custom_wait_events--1.0.sql  |  39 +++
 .../test_custom_wait_events.c | 253 ++
 .../test_custom_wait_events.control   |   3 +
 16 files changed, 718 insertions(+), 17 deletions(-)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 588b720f57..3aee5c243f 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1117,12 +1117,12 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 

 
- Extensions can add LWLock types to the list shown in
- .  In some cases, the name
+ Extensions can add Extension and LWLock types
+ to the list shown in  and
+ . In some cases, the name
  assigned by an extension will not be available in all server processes;
- so an LWLock wait event might be reported as
- just extension rather than the
- extension-assigned name.
+ so an wait event might be reported as just extension
+ rather than the extension-assigned name.
 

  
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 9620ea9ae3..bc210cd03b 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3453,6 +3453,29 @@ if (!ptr)
 

 
+   
+Custom Wait Events for Add-ins
+
+
+Add-ins can define custom wait events that the wait event type is
+Extension.
+
+
+First, add-ins should get new one or more wait events by calling:
+
+uint32 WaitEventExtensionNew(void)
+
+Next, each individual process can use them to associate that
+a wait event string to the associated name by calling:
+
+void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name);
+
+An example can be found in

Re: Support to define custom wait events for extensions

2023-07-12 Thread Michael Paquier
On Thu, Jul 13, 2023 at 10:26:35AM +0900, Masahiro Ikeda wrote:
> Thanks for your quick response. I'll rebase for the commit.

Okay, thanks.  I'll wait for the rebased version before moving on with
the next review, then.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-12 Thread Masahiro Ikeda

On 2023-07-13 09:12, Michael Paquier wrote:

On Wed, Jul 12, 2023 at 05:46:31PM +0900, Michael Paquier wrote:

On Wed, Jul 12, 2023 at 04:52:38PM +0900, Masahiro Ikeda wrote:

If the behavior is unexpected, we need to change the current code.
I have created a patch for the areas that I felt needed to be 
changed.

- 0001-change-the-die-condition-in-generate-wait_event_type.patch
 (In addition to the above, "$continue = ",\n";" doesn't appear to be
necessary.)


die "wait event names must start with 'WAIT_EVENT_'"
  if ( $trimmedwaiteventname eq $waiteventenumname
-   && $waiteventenumname !~ /^LWLock/
-   && $waiteventenumname !~ /^Lock/);
-   $continue = ",\n";
+   && $waitclassname !~ /^WaitEventLWLock$/
+   && $waitclassname !~ /^WaitEventLock$/);

Indeed, this looks wrong as-is.  $waiteventenumname refers to the
names of the enum elements, so we could just apply a filter based on
the class names in full.  The second check in for the generation of
the c/h files uses the class names.


At the end, I have gone with an event simpler way and removed the
checks for LWLock and Lock as their hardcoded values marked as DOCONLY
satisfy this check.  The second check when generating the C and header
code has also been simplified a bit to use an exact match with the
class name.


Thanks for your quick response. I'll rebase for the commit.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-12 Thread Michael Paquier
On Wed, Jul 12, 2023 at 05:46:31PM +0900, Michael Paquier wrote:
> On Wed, Jul 12, 2023 at 04:52:38PM +0900, Masahiro Ikeda wrote:
>> If the behavior is unexpected, we need to change the current code.
>> I have created a patch for the areas that I felt needed to be changed.
>> - 0001-change-the-die-condition-in-generate-wait_event_type.patch
>>  (In addition to the above, "$continue = ",\n";" doesn't appear to be
>> necessary.)
> 
> die "wait event names must start with 'WAIT_EVENT_'"
>   if ( $trimmedwaiteventname eq $waiteventenumname
> -   && $waiteventenumname !~ /^LWLock/
> -   && $waiteventenumname !~ /^Lock/);
> -   $continue = ",\n";
> +   && $waitclassname !~ /^WaitEventLWLock$/
> +   && $waitclassname !~ /^WaitEventLock$/);
> 
> Indeed, this looks wrong as-is.  $waiteventenumname refers to the
> names of the enum elements, so we could just apply a filter based on
> the class names in full.  The second check in for the generation of
> the c/h files uses the class names.

At the end, I have gone with an event simpler way and removed the
checks for LWLock and Lock as their hardcoded values marked as DOCONLY
satisfy this check.  The second check when generating the C and header
code has also been simplified a bit to use an exact match with the
class name. 
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-12 Thread Michael Paquier
On Wed, Jul 12, 2023 at 04:52:38PM +0900, Masahiro Ikeda wrote:
> In my understanding, the first column of the row for WaitEventExtension in
> wait_event_names.txt can be any value and the above code should not die.
> But if I use the following input, it falls on the last line.
> 
>  # wait_event_names.txt
>  Section: ClassName - WaitEventExtension
> 
>  WAIT_EVENT_EXTENSION "Extension" "Waiting in an extension."
>  Extension"Extension" "Waiting in an extension."
>  EXTENSION"Extension" "Waiting in an extension."
> 
> If the behavior is unexpected, we need to change the current code.
> I have created a patch for the areas that I felt needed to be changed.
> - 0001-change-the-die-condition-in-generate-wait_event_type.patch
>  (In addition to the above, "$continue = ",\n";" doesn't appear to be
> necessary.)

die "wait event names must start with 'WAIT_EVENT_'"
  if ( $trimmedwaiteventname eq $waiteventenumname
-   && $waiteventenumname !~ /^LWLock/
-   && $waiteventenumname !~ /^Lock/);
-   $continue = ",\n";
+   && $waitclassname !~ /^WaitEventLWLock$/
+   && $waitclassname !~ /^WaitEventLock$/);

Indeed, this looks wrong as-is.  $waiteventenumname refers to the
names of the enum elements, so we could just apply a filter based on
the class names in full.  The second check in for the generation of
the c/h files uses the class names.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-12 Thread Masahiro Ikeda

On 2023-07-12 09:36, Andres Freund wrote:

Hi,

On 2023-07-11 16:45:26 +0900, Michael Paquier wrote:

+/* --
+ * Wait Events - Extension
+ *
+ * Use this category when the server process is waiting for some 
condition

+ * defined by an extension module.
+ *
+ * Extensions can define custom wait events.  First, call
+ * WaitEventExtensionNewTranche() just once to obtain a new wait 
event

+ * tranche.  The ID is allocated from a shared counter.  Next, each
+ * individual process using the tranche should call
+ * WaitEventExtensionRegisterTranche() to associate that wait event 
with

+ * a name.


What does "tranche" mean here? For LWLocks it makes some sense, it's 
used for
a set of lwlocks, not an individual one. But here that doesn't really 
seem to

apply?


Thanks for useful comments.
OK, I will change to WaitEventExtensionNewId() and 
WaitEventExtensionRegisterName().


+ * It may seem strange that each process using the tranche must 
register it
+ * separately, but dynamic shared memory segments aren't guaranteed 
to be
+ * mapped at the same address in all coordinating backends, so 
storing the
+ * registration in the main shared memory segment wouldn't work for 
that case.

+ */

I don't really see how this applies to wait events? There's no pointers
here...


Yes, I'll fix the comments.




+typedef enum
+{
+   WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
+   WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
+} WaitEventExtension;
+
+extern void WaitEventExtensionShmemInit(void);
+extern Size WaitEventExtensionShmemSize(void);
+
+extern uint32 WaitEventExtensionNewTranche(void);
+extern void WaitEventExtensionRegisterTranche(uint32 wait_event_info,



-slock_t*ShmemLock; /* spinlock for shared memory and LWLock
+slock_t*ShmemLock; /* spinlock for shared memory, LWLock
+* allocation, 
and named extension wait event
 * allocation */


I'm doubtful that it's a good idea to reuse the spinlock further. Given 
that
the patch adds WaitEventExtensionShmemInit(), why not just have a lock 
in

there?


OK, I'll create a new spinlock for the purpose.



+/*
+ * Allocate a new event ID and return the wait event info.
+ */
+uint32
+WaitEventExtensionNewTranche(void)
+{
+   uint16  eventId;
+
+   SpinLockAcquire(ShmemLock);
+   eventId = (*WaitEventExtensionCounter)++;
+   SpinLockRelease(ShmemLock);
+
+   return PG_WAIT_EXTENSION | eventId;
+}


It seems quite possible to run out space in WaitEventExtensionCounter, 
so this

should error out in that case.


OK, I'll do so.



+/*
+ * Register a dynamic tranche name in the lookup table of the current 
process.

+ *
+ * This routine will save a pointer to the wait event tranche name 
passed
+ * as an argument, so the name should be allocated in a 
backend-lifetime context

+ * (shared memory, TopMemoryContext, static constant, or similar).
+ *
+ * The "wait_event_name" will be user-visible as a wait event name, 
so try to

+ * use a name that fits the style for those.
+ */
+void
+WaitEventExtensionRegisterTranche(uint32 wait_event_info,
+ const char 
*wait_event_name)
+{
+   uint16  eventId;
+
+   /* Check wait event class. */
+   Assert((wait_event_info & 0xFF00) == PG_WAIT_EXTENSION);
+
+   eventId = wait_event_info & 0x;
+
+   /* This should only be called for user-defined tranches. */
+   if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
+   return;


Why not assert out in that case then?


OK, I'll add the assertion for eventID.



+/*
+ * Return the name of an Extension wait event ID.
+ */
+static const char *
+GetWaitEventExtensionIdentifier(uint16 eventId)
+{
+   /* Build-in tranche? */


*built


I will fix it.



+   if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
+   return "Extension";
+
+   /*
+	 * It's an extension tranche, so look in 
WaitEventExtensionTrancheNames[].
+	 * However, it's possible that the tranche has never been registered 
by
+	 * calling WaitEventExtensionRegisterTranche() in the current 
process, in

+* which case give up and return "Extension".
+*/
+   eventId -= NUM_BUILTIN_WAIT_EVENT_EXTENSION;
+
+   if (eventId >= WaitEventExtensionTrancheNamesAllocated ||
+   WaitEventExtensionTrancheNames[eventId] == NULL)
+   return "Extension";


I'd return something different here, otherwise something that's 
effectively a

bug is not distinguishable from the built


It is a good idea. It would be good to name it "unknown wait event", the 
same as

pgstat_get_wait_activity(), etc.



+++ b/src/test/modules/test_custom_wait_events/t/001_basic.pl
@@ -0,0 +1,34 @@
+# Copyright (c) 2023, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+

Re: Support to define custom wait events for extensions

2023-07-12 Thread Masahiro Ikeda

On 2023-07-12 02:39, Tristan Partin wrote:

From bf06b8100cb747031959fe81a2d19baabc4838cf Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Fri, 16 Jun 2023 11:53:29 +0900
Subject: [PATCH 1/2] Support custom wait events for extensions.


+ * This is indexed by event ID minus 
NUM_BUILTIN_WAIT_EVENT_EXTENSION, and
+ * stores the names of all dynamically-created event ID known to the 
current

+ * process.  Any unused entries in the array will contain NULL.


The second ID should be plural.


Thanks for reviewing. Yes, I'll fix it.


+   /* If necessary, create or enlarge array. */
+   if (eventId >= ExtensionWaitEventTrancheNamesAllocated)
+   {
+   int newalloc;
+
+   newalloc = pg_nextpower2_32(Max(8, eventId + 1));


Given the context of our last conversation, I assume this code was
copied from somewhere else. Since this is new code, I think it would
make more sense if newalloc was a uint16 or size_t.


As Michael-san said, I used LWLockRegisterTranche() as a reference.
I think it is a good idea to fix the current master. I'll modify the
above code accordingly.


From what I undersatnd, Neon differs from upstream in some way related
to this patch. I am trying to ascertain how that is. I hope to provide
more feedback when I learn more about it.


Oh, it was unexpected for me. Thanks for researching the reason.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-07-12 Thread Masahiro Ikeda

On 2023-07-11 16:45, Michael Paquier wrote:

On Fri, Jun 23, 2023 at 05:56:26PM +0900, Masahiro Ikeda wrote:

I updated the patches to handle the warning mentioned
by PostgreSQL Patch Tester, and removed unnecessary spaces.


I have begun hacking on that, and the API layer inspired from the
LWLocks is sound.  I have been playing with it in my own extensions
and it is nice to be able to plug in custom wait events into
pg_stat_activity, particularly for bgworkers.  Finally.


Great!


The patch needed a rebase after the recent commit that introduced the
automatic generation of docs and code for wait events.  It requires
two tweaks in generate-wait_event_types.pl, feel free to double-check
them.


Thanks for rebasing. I confirmed it works with the current master.

I know this is a little off-topic from what we're talking about here,
but I'm curious about generate-wait_event_types.pl.

 # generate-wait_event_types.pl
 -  # An exception is required for LWLock and Lock as these don't require
 -  # any C and header files generated.
 +	# An exception is required for Extension, LWLock and Lock as these 
don't

 +  # require any C and header files generated.
die "wait event names must start with 'WAIT_EVENT_'"
  if ( $trimmedwaiteventname eq $waiteventenumname
 +  && $waiteventenumname !~ /^Extension/
&& $waiteventenumname !~ /^LWLock/
&& $waiteventenumname !~ /^Lock/);

In my understanding, the first column of the row for WaitEventExtension 
in

wait_event_names.txt can be any value and the above code should not die.
But if I use the following input, it falls on the last line.

 # wait_event_names.txt
 Section: ClassName - WaitEventExtension

 WAIT_EVENT_EXTENSION   "Extension"   "Waiting in an extension."
 Extension  "Extension"   "Waiting in an extension."
 EXTENSION  "Extension"   "Waiting in an extension."

If the behavior is unexpected, we need to change the current code.
I have created a patch for the areas that I felt needed to be changed.
- 0001-change-the-die-condition-in-generate-wait_event_type.patch
 (In addition to the above, "$continue = ",\n";" doesn't appear to be 
necessary.)




Some of the new structures and routine names don't quite reflect the
fact that we have wait events for extensions, so I have taken a stab
at that.


Sorry. I confirmed the change.



Note that the test module test_custom_wait_events would crash if
attempting to launch a worker when not loaded in
shared_preload_libraries, so we'd better have some protection in
wait_worker_launch() (this function should be renamed as well).


OK, I will handle it. Since Andres gave me other comments for the
test module, I'll think about what is best.



Attached is a rebased patch that I have begun tweaking here and
there.  For now, the patch is moved as waiting on author.  I have
merged the test module with the main patch for the moment, for
simplicity.  A split is straight-forward as the code paths touched are
different.

Another and *very* important thing is that we are going to require
some documentation in xfunc.sgml to explain how to use these routines
and what to expect from them.  Ikeda-san, could you write some?  You
could look at the part about shmem and LWLock to get some
inspiration.


OK. Yes, I planned to write documentation.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 5198fc6302a3bf4232252b23b45d39d987e736bc Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Wed, 12 Jul 2023 16:28:27 +0900
Subject: [PATCH] change the die condition in generate-wait_event_types.pl

---
 src/backend/utils/activity/generate-wait_event_types.pl | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/activity/generate-wait_event_types.pl b/src/backend/utils/activity/generate-wait_event_types.pl
index 6d1a2af42a..fbe011039a 100644
--- a/src/backend/utils/activity/generate-wait_event_types.pl
+++ b/src/backend/utils/activity/generate-wait_event_types.pl
@@ -89,9 +89,8 @@ foreach my $line (@lines_sorted)
 	# any C and header files generated.
 	die "wait event names must start with 'WAIT_EVENT_'"
 	  if ( $trimmedwaiteventname eq $waiteventenumname
-		&& $waiteventenumname !~ /^LWLock/
-		&& $waiteventenumname !~ /^Lock/);
-	$continue = ",\n";
+		&& $waitclassname !~ /^WaitEventLWLock$/
+		&& $waitclassname !~ /^WaitEventLock$/);
 	push(@{ $hashwe{$waitclassname} }, @waiteventlist);
 }
 
-- 
2.25.1



Re: Support to define custom wait events for extensions

2023-07-12 Thread Michael Paquier
On Tue, Jul 11, 2023 at 05:36:47PM -0700, Andres Freund wrote:
> On 2023-07-11 16:45:26 +0900, Michael Paquier wrote:
>> +$node->init;
>> +$node->append_conf(
>> +'postgresql.conf',
>> +"shared_preload_libraries = 'test_custom_wait_events'"
>> +);
>> +$node->start;
> 
> I think this should also test registering a wait event later.

Yup, agreed that the coverage is not sufficient.

> > @@ -0,0 +1,188 @@
> > +/*--
> > + *
> > + * test_custom_wait_events.c
> > + * Code for testing custom wait events
> > + *
> > + * This code initializes a custom wait event in shmem_request_hook() and
> > + * provide a function to launch a background worker waiting forever
> > + * with the custom wait event.
> 
> Isn't this vast overkill?  Why not just have a simple C function that waits
> with a custom wait event, until cancelled? That'd maybe 1/10th of the LOC.

Hmm.  You mean in the shape of a TAP test where a backend registers a
wait event by itself in a SQL function that waits for a certain amount
of time with a WaitLatch(), then we use a second poll_query_until()
that checks if the a wait event is stored in pg_stat_activity?  With
something like what's done at the end of 001_stream_rep.pl, that
should be stable, I guess..
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-11 Thread Andres Freund
Hi,

On 2023-07-11 16:45:26 +0900, Michael Paquier wrote:
> +/* --
> + * Wait Events - Extension
> + *
> + * Use this category when the server process is waiting for some condition
> + * defined by an extension module.
> + *
> + * Extensions can define custom wait events.  First, call
> + * WaitEventExtensionNewTranche() just once to obtain a new wait event
> + * tranche.  The ID is allocated from a shared counter.  Next, each
> + * individual process using the tranche should call
> + * WaitEventExtensionRegisterTranche() to associate that wait event with
> + * a name.

What does "tranche" mean here? For LWLocks it makes some sense, it's used for
a set of lwlocks, not an individual one. But here that doesn't really seem to
apply?


> + * It may seem strange that each process using the tranche must register it
> + * separately, but dynamic shared memory segments aren't guaranteed to be
> + * mapped at the same address in all coordinating backends, so storing the
> + * registration in the main shared memory segment wouldn't work for that 
> case.
> + */

I don't really see how this applies to wait events? There's no pointers
here...


> +typedef enum
> +{
> + WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION,
> + WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
> +} WaitEventExtension;
> +
> +extern void WaitEventExtensionShmemInit(void);
> +extern Size WaitEventExtensionShmemSize(void);
> +
> +extern uint32 WaitEventExtensionNewTranche(void);
> +extern void WaitEventExtensionRegisterTranche(uint32 wait_event_info,

> -slock_t*ShmemLock;   /* spinlock for shared memory 
> and LWLock
> +slock_t*ShmemLock;   /* spinlock for shared memory, 
> LWLock
> +  * allocation, 
> and named extension wait event
>* allocation */

I'm doubtful that it's a good idea to reuse the spinlock further. Given that
the patch adds WaitEventExtensionShmemInit(), why not just have a lock in
there?



> +/*
> + * Allocate a new event ID and return the wait event info.
> + */
> +uint32
> +WaitEventExtensionNewTranche(void)
> +{
> + uint16  eventId;
> +
> + SpinLockAcquire(ShmemLock);
> + eventId = (*WaitEventExtensionCounter)++;
> + SpinLockRelease(ShmemLock);
> +
> + return PG_WAIT_EXTENSION | eventId;
> +}

It seems quite possible to run out space in WaitEventExtensionCounter, so this
should error out in that case.


> +/*
> + * Register a dynamic tranche name in the lookup table of the current 
> process.
> + *
> + * This routine will save a pointer to the wait event tranche name passed
> + * as an argument, so the name should be allocated in a backend-lifetime 
> context
> + * (shared memory, TopMemoryContext, static constant, or similar).
> + *
> + * The "wait_event_name" will be user-visible as a wait event name, so try to
> + * use a name that fits the style for those.
> + */
> +void
> +WaitEventExtensionRegisterTranche(uint32 wait_event_info,
> +   const char 
> *wait_event_name)
> +{
> + uint16  eventId;
> +
> + /* Check wait event class. */
> + Assert((wait_event_info & 0xFF00) == PG_WAIT_EXTENSION);
> +
> + eventId = wait_event_info & 0x;
> +
> + /* This should only be called for user-defined tranches. */
> + if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
> + return;

Why not assert out in that case then?


> +/*
> + * Return the name of an Extension wait event ID.
> + */
> +static const char *
> +GetWaitEventExtensionIdentifier(uint16 eventId)
> +{
> + /* Build-in tranche? */

*built

> + if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
> + return "Extension";
> +
> + /*
> +  * It's an extension tranche, so look in 
> WaitEventExtensionTrancheNames[].
> +  * However, it's possible that the tranche has never been registered by
> +  * calling WaitEventExtensionRegisterTranche() in the current process, 
> in
> +  * which case give up and return "Extension".
> +  */
> + eventId -= NUM_BUILTIN_WAIT_EVENT_EXTENSION;
> +
> + if (eventId >= WaitEventExtensionTrancheNamesAllocated ||
> + WaitEventExtensionTrancheNames[eventId] == NULL)
> + return "Extension";

I'd return something different here, otherwise something that's effectively a
bug is not distinguishable from the built


> +++ b/src/test/modules/test_custom_wait_events/t/001_basic.pl
> @@ -0,0 +1,34 @@
> +# Copyright (c) 2023, PostgreSQL Global Development Group
> +
> +use strict;
> +use warnings;
> +
> +use PostgreSQL::Test::Cluster;
> +use PostgreSQL::Test::Utils;
> +use Test::More;
> +
> +my $node = PostgreSQL::Test::Cluster->new('main');
> +
> +$node->init;
> +$node->append_conf(
> + 'postgresql.conf',
> + "shared_preload_libraries = 'test_custom_wait_events'"
> +);
> 

Re: Support to define custom wait events for extensions

2023-07-11 Thread Michael Paquier
On Tue, Jul 11, 2023 at 12:39:52PM -0500, Tristan Partin wrote:
> Given the context of our last conversation, I assume this code was
> copied from somewhere else. Since this is new code, I think it would
> make more sense if newalloc was a uint16 or size_t.

This style comes from LWLockRegisterTranche() in lwlock.c.  Do you
think that it would be more adapted to change that to
pg_nextpower2_size_t() with a Size?  We could do that for the existing
code on HEAD as an improvement.

> From what I understand, Neon differs from upstream in some way related
> to this patch. I am trying to ascertain how that is. I hope to provide
> more feedback when I learn more about it.

Hmm, okay, that would nice to hear about to make sure that the
approach taken on this thread is able to cover what you are looking
for.  So you mean that Neon has been using something similar to
register wait events in the backend?  Last time I looked at the Neon
repo, I did not get the impression that there was a custom patch for
Postgres in this area.  All the in-core code paths using
WAIT_EVENT_EXTENSION would gain from the APIs added here, FWIW.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-07-11 Thread Tristan Partin
> From bf06b8100cb747031959fe81a2d19baabc4838cf Mon Sep 17 00:00:00 2001
> From: Masahiro Ikeda 
> Date: Fri, 16 Jun 2023 11:53:29 +0900
> Subject: [PATCH 1/2] Support custom wait events for extensions.

> + * This is indexed by event ID minus NUM_BUILTIN_WAIT_EVENT_EXTENSION, and
> + * stores the names of all dynamically-created event ID known to the current
> + * process.  Any unused entries in the array will contain NULL.

The second ID should be plural.

> +   /* If necessary, create or enlarge array. */
> +   if (eventId >= ExtensionWaitEventTrancheNamesAllocated)
> +   {
> +   int newalloc;
> +
> +   newalloc = pg_nextpower2_32(Max(8, eventId + 1));

Given the context of our last conversation, I assume this code was
copied from somewhere else. Since this is new code, I think it would
make more sense if newalloc was a uint16 or size_t.

>From what I undersatnd, Neon differs from upstream in some way related
to this patch. I am trying to ascertain how that is. I hope to provide
more feedback when I learn more about it.

-- 
Tristan Partin
Neon (https://neon.tech)




Re: Support to define custom wait events for extensions

2023-07-11 Thread Michael Paquier
On Fri, Jun 23, 2023 at 05:56:26PM +0900, Masahiro Ikeda wrote:
> I updated the patches to handle the warning mentioned
> by PostgreSQL Patch Tester, and removed unnecessary spaces.

I have begun hacking on that, and the API layer inspired from the
LWLocks is sound.  I have been playing with it in my own extensions
and it is nice to be able to plug in custom wait events into
pg_stat_activity, particularly for bgworkers.  Finally.

The patch needed a rebase after the recent commit that introduced the
automatic generation of docs and code for wait events.  It requires
two tweaks in generate-wait_event_types.pl, feel free to double-check
them.

Some of the new structures and routine names don't quite reflect the
fact that we have wait events for extensions, so I have taken a stab
at that.

Note that the test module test_custom_wait_events would crash if
attempting to launch a worker when not loaded in
shared_preload_libraries, so we'd better have some protection in
wait_worker_launch() (this function should be renamed as well).

Attached is a rebased patch that I have begun tweaking here and
there.  For now, the patch is moved as waiting on author.  I have
merged the test module with the main patch for the moment, for
simplicity.  A split is straight-forward as the code paths touched are
different.

Another and *very* important thing is that we are going to require
some documentation in xfunc.sgml to explain how to use these routines
and what to expect from them.  Ikeda-san, could you write some?  You
could look at the part about shmem and LWLock to get some
inspiration.
--
Michael
From 630f78822534171bb8839c79d0fdca3bb8268a95 Mon Sep 17 00:00:00 2001
From: Michael Paquier 
Date: Tue, 11 Jul 2023 16:41:35 +0900
Subject: [PATCH v5] Support custom wait events for extensions.

To support custom wait events, it add 2 APIs to allocate new wait events
dynamically.

The APIs are
* ExtensionWaitEventNewTranche()
* ExtensionWaitEventRegisterTranche()

These are similar to the existing LWLockNewTrancheId() and
LWLockRegisterTranche().

First, extension should call ExtensionWaitEventNewTranche() to get one
or more wait event "tranches", which are ID is allocated from a shared
counter.  Next, each individual process can use the tranche numbers with
ExtensionWaitEventRegisterTranche() to associate that a wait event
string to the associated name.

Note that this includes a test module, which perhaps should be split
later into its own commit.
---
 src/include/utils/wait_event.h|  31 +++
 src/backend/storage/ipc/ipci.c|   3 +
 src/backend/storage/ipc/shmem.c   |   3 +-
 .../activity/generate-wait_event_types.pl |  12 +-
 src/backend/utils/activity/wait_event.c   | 149 +-
 .../utils/activity/wait_event_names.txt   |   2 +-
 src/test/modules/Makefile |   1 +
 src/test/modules/meson.build  |   1 +
 .../test_custom_wait_events/.gitignore|   2 +
 .../modules/test_custom_wait_events/Makefile  |  23 +++
 .../test_custom_wait_events/meson.build   |  33 +++
 .../test_custom_wait_events/t/001_basic.pl|  34 
 .../test_custom_wait_events--1.0.sql  |  14 ++
 .../test_custom_wait_events.c | 188 ++
 .../test_custom_wait_events.control   |   3 +
 15 files changed, 484 insertions(+), 15 deletions(-)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index 4517425f84..dfcaf8c506 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -67,6 +67,37 @@ pgstat_report_wait_start(uint32 wait_event_info)
 	*(volatile uint32 *) my_wait_event_info = wait_event_info;
 }
 
+/* --
+ * Wait Events - Extension
+ *
+ * Use this category when the server process is waiting for some condition
+ * defined by an extension module.
+ *
+ * Extensions can define custom wait events.  First, call
+ * WaitEventExtensionNewTranche() just once to obtain a new wait event
+ * tranche.  The ID is allocated from a shared counter.  Next, each
+ * individual process using the tranche should call
+ * WaitEventExtensionRegisterTranche() to associate that wait event with
+ * a name.
+ *
+ * It may seem strange that each process using the tranche must register it
+ * separately, but dynamic shared memory segments aren't guaranteed to be
+ * mapped at the same address in all coordinating 

Re: Support to define custom wait events for extensions

2023-06-23 Thread Masahiro Ikeda

Hi,

I updated the patches to handle the warning mentioned
by PostgreSQL Patch Tester, and removed unnecessary spaces.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 1bb78fa2cbe6b030cea7a570bec88bd4d68f314a Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Fri, 23 Jun 2023 17:38:38 +0900
Subject: [PATCH 2/2] Add test codes for custom wait events

---
 src/test/modules/Makefile |   1 +
 src/test/modules/meson.build  |   1 +
 .../test_custom_wait_events/.gitignore|   2 +
 .../modules/test_custom_wait_events/Makefile  |  23 +++
 .../test_custom_wait_events/meson.build   |  33 
 .../test_custom_wait_events/t/001_basic.pl|  34 
 .../test_custom_wait_events--1.0.sql  |  14 ++
 .../test_custom_wait_events.c | 182 ++
 .../test_custom_wait_events.control   |   3 +
 9 files changed, 293 insertions(+)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 6331c976dc..84312b7e57 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -17,6 +17,7 @@ SUBDIRS = \
 		  test_bloomfilter \
 		  test_copy_callbacks \
 		  test_custom_rmgrs \
+		  test_custom_wait_events \
 		  test_ddl_deparse \
 		  test_extensions \
 		  test_ginpostinglist \
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index 17d369e378..83a1d8fd19 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -14,6 +14,7 @@ subdir('ssl_passphrase_callback')
 subdir('test_bloomfilter')
 subdir('test_copy_callbacks')
 subdir('test_custom_rmgrs')
+subdir('test_custom_wait_events')
 subdir('test_ddl_deparse')
 subdir('test_extensions')
 subdir('test_ginpostinglist')
diff --git a/src/test/modules/test_custom_wait_events/.gitignore b/src/test/modules/test_custom_wait_events/.gitignore
new file mode 100644
index 00..716e17f5a2
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/.gitignore
@@ -0,0 +1,2 @@
+# Generated subdirectories
+/tmp_check/
diff --git a/src/test/modules/test_custom_wait_events/Makefile b/src/test/modules/test_custom_wait_events/Makefile
new file mode 100644
index 00..dda365d523
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_custom_wait_events/Makefile
+
+MODULE_big = test_custom_wait_events
+OBJS = \
+	$(WIN32RES) \
+	test_custom_wait_events.o
+PGFILEDESC = "test_custom_wait_events - test custom wait events"
+
+EXTENSION = test_custom_wait_events
+DATA = test_custom_wait_events--1.0.sql
+
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_custom_wait_events
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_custom_wait_events/meson.build b/src/test/modules/test_custom_wait_events/meson.build
new file mode 100644
index 00..8ad073e577
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/meson.build
@@ -0,0 +1,33 @@
+# Copyright (c) PostgreSQL Global Development Group
+
+test_custom_wait_events = files(
+  'test_custom_wait_events.c',
+)
+
+if host_system == 'windows'
+  test_custom_wait_events += rc_lib_gen.process(win32ver_rc, extra_args: [
+'--NAME', 'test_custom_wait_events',
+'--FILEDESC', 'test_custom_wait_events - test custom wait events',])
+endif
+
+test_custom_wait_events = shared_module('test_custom_wait_events',
+  test_custom_wait_events,
+  kwargs: pg_test_mod_args,
+)
+test_install_libs += test_custom_wait_events
+
+test_install_data += files(
+  'test_custom_wait_events.control',
+  'test_custom_wait_events--1.0.sql',
+)
+
+tests += {
+  'name': 'test_custom_wait_events',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+'tests': [
+  't/001_basic.pl',
+],
+  },
+}
diff --git a/src/test/modules/test_custom_wait_events/t/001_basic.pl b/src/test/modules/test_custom_wait_events/t/001_basic.pl
new file mode 100644
index 00..b43c82a713
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/t/001_basic.pl
@@ -0,0 +1,34 @@
+# Copyright (c) 2023, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node = 

Re: Support to define custom wait events for extensions

2023-06-21 Thread Masahiro Ikeda

On 2023-06-20 18:26, Masahiro Ikeda wrote:

The followings are TODO items.
* to check that meson.build works since I tested with old command 
`make` now


I test with meson and I updated the patches to work with it.
My test procedure is the following.

```
export builddir=/mnt/tmp/build
export prefix=/mnt/tmp/master

# setup
meson setup $builddir --prefix=$prefix -Ddebug=true -Dcassert=true 
-Dtap_tests=enabled


# build and install with src/test/modules
ninja -C $builddir install install-test-files

# test
meson test -v -C $builddir
meson test -v -C $builddir --suite test_custom_wait_events  # run the 
test only

```

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 901b75d31070ef0029557db6981c98e06f5c16c3 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Tue, 20 Jun 2023 17:59:34 +0900
Subject: [PATCH 2/2] Add test codes for custom wait events

---
 src/test/modules/Makefile |   1 +
 src/test/modules/meson.build  |   1 +
 .../test_custom_wait_events/.gitignore|   2 +
 .../modules/test_custom_wait_events/Makefile  |  23 +++
 .../test_custom_wait_events/meson.build   |  33 
 .../test_custom_wait_events/t/001_basic.pl|  34 
 .../test_custom_wait_events--1.0.sql  |  14 ++
 .../test_custom_wait_events.c | 182 ++
 .../test_custom_wait_events.control   |   3 +
 9 files changed, 293 insertions(+)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 6331c976dc..84312b7e57 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -17,6 +17,7 @@ SUBDIRS = \
 		  test_bloomfilter \
 		  test_copy_callbacks \
 		  test_custom_rmgrs \
+		  test_custom_wait_events \
 		  test_ddl_deparse \
 		  test_extensions \
 		  test_ginpostinglist \
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index 17d369e378..83a1d8fd19 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -14,6 +14,7 @@ subdir('ssl_passphrase_callback')
 subdir('test_bloomfilter')
 subdir('test_copy_callbacks')
 subdir('test_custom_rmgrs')
+subdir('test_custom_wait_events')
 subdir('test_ddl_deparse')
 subdir('test_extensions')
 subdir('test_ginpostinglist')
diff --git a/src/test/modules/test_custom_wait_events/.gitignore b/src/test/modules/test_custom_wait_events/.gitignore
new file mode 100644
index 00..716e17f5a2
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/.gitignore
@@ -0,0 +1,2 @@
+# Generated subdirectories
+/tmp_check/
diff --git a/src/test/modules/test_custom_wait_events/Makefile b/src/test/modules/test_custom_wait_events/Makefile
new file mode 100644
index 00..dda365d523
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_custom_wait_events/Makefile
+
+MODULE_big = test_custom_wait_events
+OBJS = \
+	$(WIN32RES) \
+	test_custom_wait_events.o
+PGFILEDESC = "test_custom_wait_events - test custom wait events"
+
+EXTENSION = test_custom_wait_events
+DATA = test_custom_wait_events--1.0.sql
+
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_custom_wait_events
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_custom_wait_events/meson.build b/src/test/modules/test_custom_wait_events/meson.build
new file mode 100644
index 00..8ad073e577
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/meson.build
@@ -0,0 +1,33 @@
+# Copyright (c) PostgreSQL Global Development Group
+
+test_custom_wait_events = files(
+  'test_custom_wait_events.c',
+)
+
+if host_system == 'windows'
+  test_custom_wait_events += rc_lib_gen.process(win32ver_rc, extra_args: [
+'--NAME', 'test_custom_wait_events',
+'--FILEDESC', 'test_custom_wait_events - test custom wait events',])
+endif
+
+test_custom_wait_events = shared_module('test_custom_wait_events',
+  test_custom_wait_events,
+  kwargs: pg_test_mod_args,
+)
+test_install_libs += test_custom_wait_events
+
+test_install_data += files(
+  'test_custom_wait_events.control',
+  'test_custom_wait_events--1.0.sql',
+)
+
+tests += {
+  'name': 'test_custom_wait_events',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+

Re: Support to define custom wait events for extensions

2023-06-20 Thread Masahiro Ikeda

Hi,

I updated the patches. The main changes are
* to support only dynamic wait event allocation
* to add a regression test
I appreciate any feedback.

The followings are TODO items.
* to check that meson.build works since I tested with old command `make` 
now

* to make documents
* to add custom wait events for existing contrib modules (ex. 
postgres_fdw)


Regards,
--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 206ce9e1d74d1449b50cfc765936172de98687e8 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Tue, 20 Jun 2023 17:59:34 +0900
Subject: [PATCH 2/2] Add test codes for custom wait events

---
 src/test/modules/Makefile |   1 +
 .../test_custom_wait_events/.gitignore|   2 +
 .../modules/test_custom_wait_events/Makefile  |  23 +++
 .../test_custom_wait_events/meson.build   |  33 
 .../test_custom_wait_events/t/001_basic.pl|  34 
 .../test_custom_wait_events--1.0.sql  |  14 ++
 .../test_custom_wait_events.c | 182 ++
 .../test_custom_wait_events.control   |   3 +
 8 files changed, 292 insertions(+)
 create mode 100644 src/test/modules/test_custom_wait_events/.gitignore
 create mode 100644 src/test/modules/test_custom_wait_events/Makefile
 create mode 100644 src/test/modules/test_custom_wait_events/meson.build
 create mode 100644 src/test/modules/test_custom_wait_events/t/001_basic.pl
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events--1.0.sql
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.c
 create mode 100644 src/test/modules/test_custom_wait_events/test_custom_wait_events.control

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 6331c976dc..84312b7e57 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -17,6 +17,7 @@ SUBDIRS = \
 		  test_bloomfilter \
 		  test_copy_callbacks \
 		  test_custom_rmgrs \
+		  test_custom_wait_events \
 		  test_ddl_deparse \
 		  test_extensions \
 		  test_ginpostinglist \
diff --git a/src/test/modules/test_custom_wait_events/.gitignore b/src/test/modules/test_custom_wait_events/.gitignore
new file mode 100644
index 00..716e17f5a2
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/.gitignore
@@ -0,0 +1,2 @@
+# Generated subdirectories
+/tmp_check/
diff --git a/src/test/modules/test_custom_wait_events/Makefile b/src/test/modules/test_custom_wait_events/Makefile
new file mode 100644
index 00..dda365d523
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_custom_wait_events/Makefile
+
+MODULE_big = test_custom_wait_events
+OBJS = \
+	$(WIN32RES) \
+	test_custom_wait_events.o
+PGFILEDESC = "test_custom_wait_events - test custom wait events"
+
+EXTENSION = test_custom_wait_events
+DATA = test_custom_wait_events--1.0.sql
+
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_custom_wait_events
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_custom_wait_events/meson.build b/src/test/modules/test_custom_wait_events/meson.build
new file mode 100644
index 00..da2b720f8f
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/meson.build
@@ -0,0 +1,33 @@
+# Copyright (c) 2022-2023, PostgreSQL Global Development Group
+
+test_custom_wait_events = files(
+  'test_custom_wait_events.c',
+)
+
+if host_system == 'windows'
+  test_custom_wait_events += rc_lib_gen.process(win32ver_rc, extra_args: [
+'--NAME', 'test_custom_wait_events',
+'--FILEDESC', 'test_custom_wait_events - test custom wait events',])
+endif
+
+test_custom_wait_events = shared_module('test_custom_wait_events',
+  test_custom_wait_events,
+  kwargs: pg_test_mod_args,
+)
+test_install_libs += test_custom_wait_events
+
+test_install_data += files(
+  'test_custom_wait_events.control',
+  'test_custom_wait_events--1.0.sql',
+)
+
+tests += {
+  'name': 'test_custom_wait_events',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+'tests': [
+  't/001_basic.pl',
+],
+  },
+}
diff --git a/src/test/modules/test_custom_wait_events/t/001_basic.pl b/src/test/modules/test_custom_wait_events/t/001_basic.pl
new file mode 100644
index 00..59ba14919b
--- /dev/null
+++ b/src/test/modules/test_custom_wait_events/t/001_basic.pl
@@ -0,0 +1,34 @@
+# Copyright (c) 2021-2023, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+
+$node->init;
+$node->append_conf(
+	'postgresql.conf', 
+	"shared_preload_libraries = 'test_custom_wait_events'"
+);
+$node->start;
+
+# setup
+$node->safe_psql('postgres', 'CREATE EXTENSION 

Re: Support to define custom wait events for extensions

2023-06-16 Thread Masahiro Ikeda
On 2023/06/17 1:16, Tristan Partin wrote:
> I will take a look at your V2 when it is ready! I will also pass along
> that this is wanted by Neon customers :).
Thanks!

Regards,
-- 
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-06-16 Thread Tristan Partin
I will take a look at your V2 when it is ready! I will also pass along
that this is wanted by Neon customers :).

-- 
Tristan Partin
Neon (https://neon.tech)




Re: Support to define custom wait events for extensions

2023-06-16 Thread Masahiro Ikeda

On 2023-06-16 16:46, Michael Paquier wrote:

On Fri, Jun 16, 2023 at 11:14:05AM +0900, Masahiro Ikeda wrote:

I tried to query on pg_stat_activity to check the background worker
invoked by pg_prewarm. But, I found that pg_stat_activity doesn't show
it although I may be missing something...

So, I tried to implement TAP tests. But I have a problem with it.
I couldn't find the way to check the status of another backend
while the another backend wait with custom wait events.


Hmm.  Right.  It seems to me that BGWORKER_BACKEND_DATABASE_CONNECTION
is required in this case, with BackgroundWorkerInitializeConnection()
to connect to a database (or not, like the logical replication
launcher if only access to shared catalogs is wanted).

I have missed that the leader process of pg_prewarm does not use that,
because it has no need to connect to a database, but its workers do.
So it is not going to show up in pg_stat_activity.


Yes. Thanks to your advice, I understood that
BGWORKER_BACKEND_DATABASE_CONNECTION is the reason.

I could make the TAP test that invokes a background worker waiting 
forever
and checks its custom wait event in pg_stat_activity. So, I'll make 
patches

including test codes next week.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-06-16 Thread Michael Paquier
On Fri, Jun 16, 2023 at 11:14:05AM +0900, Masahiro Ikeda wrote:
> I tried to query on pg_stat_activity to check the background worker
> invoked by pg_prewarm. But, I found that pg_stat_activity doesn't show
> it although I may be missing something...
> 
> So, I tried to implement TAP tests. But I have a problem with it.
> I couldn't find the way to check the status of another backend
> while the another backend wait with custom wait events.

Hmm.  Right.  It seems to me that BGWORKER_BACKEND_DATABASE_CONNECTION
is required in this case, with BackgroundWorkerInitializeConnection()
to connect to a database (or not, like the logical replication
launcher if only access to shared catalogs is wanted).

I have missed that the leader process of pg_prewarm does not use that,
because it has no need to connect to a database, but its workers do.
So it is not going to show up in pg_stat_activity.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-06-15 Thread Masahiro Ikeda

On 2023-06-16 01:13, Tristan Partin wrote:

We had this on our list of things to do at Neon, so it is a nice
surprise that you brought up an initial patchset :). It was also my
first time looking up the word tranche.


What a coincidence! I came up with the idea when I used Neon with
postgres_fdw. As a Neon user, I also feel the feature is important.

Same as you. Thanks to Michael and Drouvot, I got to know the word 
tranche

and the related existing code.


From 59a118402e5e59685fb9e0fb086872e25a405736 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 15 Jun 2023 12:57:29 +0900
Subject: [PATCH 2/3] Support to define custom wait events for 
extensions.



Currently, only one PG_WAIT_EXTENSION event can be used as a
wait event for extensions. Therefore, in environments with multiple
extensions are installed, it could take time to identify bottlenecks.


"extensions are installed" should be "extensions installed".


+#define NUM_BUILDIN_WAIT_EVENT_EXTENSION   \
+   (WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - 
WAIT_EVENT_EXTENSION)


Should that be NUM_BUILTIN_WAIT_EVENT_EXTENSION?


Thanks for your comments.
Yes, I'll fix it.

+   NamedExtensionWaitEventTrancheRequestArray = 
(NamedExtensionWaitEventTrancheRequest *)

+   MemoryContextAlloc(TopMemoryContext,
+  
NamedExtensionWaitEventTrancheRequestsAllocated
+  * 
sizeof(NamedExtensionWaitEventTrancheRequest));


I can't tell from reading other Postgres code when one should cast the
return value of MemoryContextAlloc(). Seems unnecessary to me.


I referenced RequestNamedLWLockTranche() and it looks ok to me.

```
void
RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest *)
MemoryContextAlloc(TopMemoryContext,
   
NamedLWLockTrancheRequestsAllocated
   * 
sizeof(NamedLWLockTrancheRequest));
```


+   if (NamedExtensionWaitEventTrancheRequestArray == NULL)
+   {
+   NamedExtensionWaitEventTrancheRequestsAllocated = 16;
+   NamedExtensionWaitEventTrancheRequestArray = 
(NamedExtensionWaitEventTrancheRequest *)

+   MemoryContextAlloc(TopMemoryContext,
+  
NamedExtensionWaitEventTrancheRequestsAllocated
+  * 
sizeof(NamedExtensionWaitEventTrancheRequest));

+   }
+
+   if (NamedExtensionWaitEventTrancheRequests >= 
NamedExtensionWaitEventTrancheRequestsAllocated)

+   {
+   int i = 
pg_nextpower2_32(NamedExtensionWaitEventTrancheRequests + 1);

+
+   NamedExtensionWaitEventTrancheRequestArray = 
(NamedExtensionWaitEventTrancheRequest *)
+   
repalloc(NamedExtensionWaitEventTrancheRequestArray,
+i * 
sizeof(NamedExtensionWaitEventTrancheRequest));

+   NamedExtensionWaitEventTrancheRequestsAllocated = i;
+   }


Do you think this code would look better in an if/else if?


Same as above. I referenced RequestNamedLWLockTranche().
I don't know if it's a good idea, but it's better to refactor the
existing code separately from this patch.

But I plan to remove the code to focus implementing dynamic allocation
similar to LWLockNewTrancheId() and LWLockRegisterTranche() as
Michael's suggestion. I think it's good idea as a first step. Is it ok 
for you?


+   int i = 
pg_nextpower2_32(NamedExtensionWaitEventTrancheRequests + 1);


In the Postgres codebase, is an int always guaranteed to be at least 32
bits? I feel like a fixed-width type would be better for tracking the
length of the array, unless Postgres prefers the Size type.


Same as above.


+   Assert(strlen(tranche_name) + 1 <= NAMEDATALEN);
+   strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);


A sizeof(request->tranche_name) would keep this code more in-sync if
size of tranche_name were to ever change, though I see sizeof
expressions in the codebase are not too common. Maybe just remove the 
+1

and make it less than rather than a less than or equal? Seems like it
might be worth noting in the docs of the function that the event name
has to be less than NAMEDATALEN, but maybe this is something extension
authors are inherently aware of?


Same as above.


---

What's the Postgres policy on the following?

for (int i = 0; ...)
for (i = 0; ...)
You are using 2 different patterns in WaitEventShmemInit() and
InitializeExtensionWaitEventTranches().


I didn't care it. I'll unify it.
Michael's replay is interesting.


+   /*
+* Copy the info abou

Re: Support to define custom wait events for extensions

2023-06-15 Thread Masahiro Ikeda

On 2023-06-15 22:21, Drouvot, Bertrand wrote:

Hi,

On 6/15/23 10:00 AM, Michael Paquier wrote:

On Thu, Jun 15, 2023 at 03:06:01PM +0900, Masahiro Ikeda wrote:

Currently, only one PG_WAIT_EXTENSION event can be used as a
wait event for extensions. Therefore, in environments with multiple
extensions are installed, it could take time to identify which
extension is the bottleneck.


Thanks for taking the time to implement a patch to do that.


+1 thanks for it!




I want to know your feedbacks. Please feel free to comment.


I think that's been cruelly missed.


Yeah, that would clearly help to diagnose which extension(s) is/are
causing the waits (if any).

I did not look at the code yet (will do) but just wanted to chime in
to support the idea.


Great! Thanks.

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-06-15 Thread Masahiro Ikeda

Thanks for replying and your kind advice!

On 2023-06-15 17:00, Michael Paquier wrote:

On Thu, Jun 15, 2023 at 03:06:01PM +0900, Masahiro Ikeda wrote:
In the core, the requested wait events are dynamically registered in 
shared

memory. The extension then obtains the wait event information with
GetNamedExtensionWaitEventTranche() and uses the value to notify the 
core

that it is waiting.

When a string representing of the wait event is requested,
it returns the name defined by calling
RequestNamedExtensionWaitEventTranche().


So this implements the equivalent of RequestNamedLWLockTranche()
followed by GetNamedLWLockTranche() to get the wait event number,
which can be used only during postmaster startup.  Do you think that
we could focus on implementing something more flexible instead, that
can be used dynamically as well as statically?  That would be similar
to LWLockNewTrancheId() and LWLockRegisterTranche(), actually, where
we would get one or more tranche IDs, then do initialization actions
in shmem based on the tranche ID(s).


OK, I agree. I'll make a patch to only support
ExtensionWaitEventNewTrancheId() and ExtensionWaitEventRegisterTranche()
similar to LWLockNewTrancheId() and LWLockRegisterTranche().


4. check the custom wait event
You can see the following results of psql-1.

query| wait_event_type |wait_event
-+-+---
 SELECT inject_wait_event(); | Extension   | custom_wait_event 
   #

requested wait event by the extension!
(1 row)

(..snip..)


A problem with this approach is that it is expensive as a test.  Do we
really need one?  There are three places that set PG_WAIT_EXTENSION in
src/test/modules/, more in /contrib, and there are modules like
pg_stat_statements that could gain from events for I/O operations, for
example.


Yes. Since it's hard to test, I thought the PoC extension
should not be committed. But, I couldn't figure out the best
way to test yet.


# TODOs

* tests on windows (since I tested on Ubuntu 20.04 only)
* add custom wait events for existing contrib modules (ex. 
postgres_fdw)

* add regression code (but, it seems to be difficult)
* others? (Please let me know)


Hmm.  You would need to maintain a state in a rather stable manner,
and SQL queries can make that difficult in the TAP tests as the wait
event information is reset each time a query finishes.  One area where
I think this gets easier is with a background worker loaded with
shared_preload_libraries that has a configurable naptime.  Looking at
what's available in the tree, the TAP tests of pg_prewarm could use
one test on pg_stat_activity with a custom wait event name
(pg_prewarm.autoprewarm_interval is 0 hence the bgworker waits
infinitely).  Note that in this case, you would need to be careful of
the case where the wait event is loaded dynamically, but like LWLocks
this should be able to work as well?


Thanks for your advice!

I tried to query on pg_stat_activity to check the background worker
invoked by pg_prewarm. But, I found that pg_stat_activity doesn't show
it although I may be missing something...

So, I tried to implement TAP tests. But I have a problem with it.
I couldn't find the way to check the status of another backend
while the another backend wait with custom wait events.

```
# TAP test I've implemented.

# wait forever with custom wait events in session1
$session1->query_safe("SELECT test_custom_wait_events_wait()");

# I want to check the wait event from another backend process
# But, the following code is never reached because the above
# query is waiting forever.
$session2->poll_query_until('postgres',
qq[SELECT
(SELECT count(*) FROM pg_stat_activity
WHERE query ~ '^SELECT test_custom_wait_events_wait'
  AND wait_event_type = 'Extension'
  AND wait_event = 'custom_wait_event'
) > 0;]);
```

If I'm missing something or you have any idea,
please let me know.

Now, I plan to

* find out more the existing tests to check wait events and locks
  (though I have already checked a little, but I couldn't find it)
* find another way to check wait event of the background worker invoked 
by extension
* look up the reason why pg_stat_activity doesn't show the background 
worker

* find a way to implement async queries in TAP tests

Regards,
--
Masahiro Ikeda
NTT DATA CORPORATION




Re: Support to define custom wait events for extensions

2023-06-15 Thread Michael Paquier
On Thu, Jun 15, 2023 at 11:13:57AM -0500, Tristan Partin wrote:
> What's the Postgres policy on the following?
> 
> for (int i = 0; ...)
> for (i = 0; ...)
> 
> You are using 2 different patterns in WaitEventShmemInit() and
> InitializeExtensionWaitEventTranches().

C99 style is OK since v12, so the style of the patch is fine.  The
older style has no urgent need to change, either.  One argument to let
the code as-is is that it could generate backpatching conflicts, while
it does not hurt as it stands.  This also means that bug fixes that
need to be applied down to 12 would be able to use C99 declarations
freely without some of the buildfarm animals running REL_11_STABLE
complaining.  I have fallen into this trap recently, actually.  See
dbd25dd.
--
Michael


signature.asc
Description: PGP signature


Re: Support to define custom wait events for extensions

2023-06-15 Thread Tristan Partin
We had this on our list of things to do at Neon, so it is a nice
surprise that you brought up an initial patchset :). It was also my
first time looking up the word tranche.

>From 59a118402e5e59685fb9e0fb086872e25a405736 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 15 Jun 2023 12:57:29 +0900
Subject: [PATCH 2/3] Support to define custom wait events for extensions.

> Currently, only one PG_WAIT_EXTENSION event can be used as a
> wait event for extensions. Therefore, in environments with multiple
> extensions are installed, it could take time to identify bottlenecks.

"extensions are installed" should be "extensions installed".

> +#define NUM_BUILDIN_WAIT_EVENT_EXTENSION   \
> +   (WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - WAIT_EVENT_EXTENSION)

Should that be NUM_BUILTIN_WAIT_EVENT_EXTENSION?

> +   NamedExtensionWaitEventTrancheRequestArray = 
> (NamedExtensionWaitEventTrancheRequest *)
> +   MemoryContextAlloc(TopMemoryContext,
> +  
> NamedExtensionWaitEventTrancheRequestsAllocated
> +  * 
> sizeof(NamedExtensionWaitEventTrancheRequest));

I can't tell from reading other Postgres code when one should cast the
return value of MemoryContextAlloc(). Seems unnecessary to me.

> +   if (NamedExtensionWaitEventTrancheRequestArray == NULL)
> +   {
> +   NamedExtensionWaitEventTrancheRequestsAllocated = 16;
> +   NamedExtensionWaitEventTrancheRequestArray = 
> (NamedExtensionWaitEventTrancheRequest *)
> +   MemoryContextAlloc(TopMemoryContext,
> +  
> NamedExtensionWaitEventTrancheRequestsAllocated
> +  * 
> sizeof(NamedExtensionWaitEventTrancheRequest));
> +   }
> +
> +   if (NamedExtensionWaitEventTrancheRequests >= 
> NamedExtensionWaitEventTrancheRequestsAllocated)
> +   {
> +   int i = 
> pg_nextpower2_32(NamedExtensionWaitEventTrancheRequests + 1);
> +
> +   NamedExtensionWaitEventTrancheRequestArray = 
> (NamedExtensionWaitEventTrancheRequest *)
> +   repalloc(NamedExtensionWaitEventTrancheRequestArray,
> +i * 
> sizeof(NamedExtensionWaitEventTrancheRequest));
> +   NamedExtensionWaitEventTrancheRequestsAllocated = i;
> +   }

Do you think this code would look better in an if/else if?

> +   int i = 
> pg_nextpower2_32(NamedExtensionWaitEventTrancheRequests + 1);

In the Postgres codebase, is an int always guaranteed to be at least 32
bits? I feel like a fixed-width type would be better for tracking the
length of the array, unless Postgres prefers the Size type.

> +   Assert(strlen(tranche_name) + 1 <= NAMEDATALEN);
> +   strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);

A sizeof(request->tranche_name) would keep this code more in-sync if
size of tranche_name were to ever change, though I see sizeof
expressions in the codebase are not too common. Maybe just remove the +1
and make it less than rather than a less than or equal? Seems like it
might be worth noting in the docs of the function that the event name
has to be less than NAMEDATALEN, but maybe this is something extension
authors are inherently aware of?

---

What's the Postgres policy on the following?

for (int i = 0; ...)
for (i = 0; ...)

You are using 2 different patterns in WaitEventShmemInit() and
InitializeExtensionWaitEventTranches().

> +   /*
> +* Copy the info about any named tranches into shared memory (so that
> +* other processes can see it), and initialize the requested wait 
> events.
> +*/
> +   if (NamedExtensionWaitEventTrancheRequests > 0)

Removing this if would allow one less indentation level. Nothing would
have to change about the containing code either since the for loop will
then not run

> +   ExtensionWaitEventCounter = (int *) ((char *) 
> NamedExtensionWaitEventTrancheArray - sizeof(int));

>From 65e25d4b27bbb6d0934872310c24ee19f89e9631 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 15 Jun 2023 13:16:00 +0900
Subject: [PATCH 3/3] Add docs to define custom wait events

> +
> + wait events are reserved by calling:
> +
> +void RequestNamedExtensionWaitEventTranche(const char *tranche_name)
> +
> + from your shmem_request_hook.  This will ensure that
> + wait event is available under the name tranche_name,
> + which the wait event type is Extension.
> + Use GetNamedExtensionWaitEventTranche
> + to get a wait event information

Re: Support to define custom wait events for extensions

2023-06-15 Thread Drouvot, Bertrand

Hi,

On 6/15/23 10:00 AM, Michael Paquier wrote:

On Thu, Jun 15, 2023 at 03:06:01PM +0900, Masahiro Ikeda wrote:

Currently, only one PG_WAIT_EXTENSION event can be used as a
wait event for extensions. Therefore, in environments with multiple
extensions are installed, it could take time to identify which
extension is the bottleneck.


Thanks for taking the time to implement a patch to do that.


+1 thanks for it!




I want to know your feedbacks. Please feel free to comment.


I think that's been cruelly missed.


Yeah, that would clearly help to diagnose which extension(s) is/are causing the 
waits (if any).

I did not look at the code yet (will do) but just wanted to chime in to support 
the idea.

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com




Re: Support to define custom wait events for extensions

2023-06-15 Thread Michael Paquier
On Thu, Jun 15, 2023 at 03:06:01PM +0900, Masahiro Ikeda wrote:
> Currently, only one PG_WAIT_EXTENSION event can be used as a
> wait event for extensions. Therefore, in environments with multiple
> extensions are installed, it could take time to identify which
> extension is the bottleneck.

Thanks for taking the time to implement a patch to do that.

> I want to know your feedbacks. Please feel free to comment.

I think that's been cruelly missed.

> In the core, the requested wait events are dynamically registered in shared
> memory. The extension then obtains the wait event information with
> GetNamedExtensionWaitEventTranche() and uses the value to notify the core
> that it is waiting.
> 
> When a string representing of the wait event is requested,
> it returns the name defined by calling
> RequestNamedExtensionWaitEventTranche().

So this implements the equivalent of RequestNamedLWLockTranche()
followed by GetNamedLWLockTranche() to get the wait event number,
which can be used only during postmaster startup.  Do you think that
we could focus on implementing something more flexible instead, that
can be used dynamically as well as statically?  That would be similar
to LWLockNewTrancheId() and LWLockRegisterTranche(), actually, where
we would get one or more tranche IDs, then do initialization actions
in shmem based on the tranche ID(s).

> 4. check the custom wait event
> You can see the following results of psql-1.
> 
> query| wait_event_type |wait_event
> -+-+---
>  SELECT inject_wait_event(); | Extension   | custom_wait_event#
> requested wait event by the extension!
> (1 row)
> 
> (..snip..)

A problem with this approach is that it is expensive as a test.  Do we
really need one?  There are three places that set PG_WAIT_EXTENSION in
src/test/modules/, more in /contrib, and there are modules like
pg_stat_statements that could gain from events for I/O operations, for
example.

> # TODOs
> 
> * tests on windows (since I tested on Ubuntu 20.04 only)
> * add custom wait events for existing contrib modules (ex. postgres_fdw)
> * add regression code (but, it seems to be difficult)
> * others? (Please let me know)

Hmm.  You would need to maintain a state in a rather stable manner,
and SQL queries can make that difficult in the TAP tests as the wait
event information is reset each time a query finishes.  One area where
I think this gets easier is with a background worker loaded with
shared_preload_libraries that has a configurable naptime.  Looking at
what's available in the tree, the TAP tests of pg_prewarm could use
one test on pg_stat_activity with a custom wait event name
(pg_prewarm.autoprewarm_interval is 0 hence the bgworker waits
infinitely).  Note that in this case, you would need to be careful of
the case where the wait event is loaded dynamically, but like LWLocks
this should be able to work as well?
--
Michael


signature.asc
Description: PGP signature


Support to define custom wait events for extensions

2023-06-15 Thread Masahiro Ikeda

Hi,

Currently, only one PG_WAIT_EXTENSION event can be used as a
wait event for extensions. Therefore, in environments with multiple
extensions are installed, it could take time to identify which
extension is the bottleneck.

So, I'd like to support new APIs to define custom wait events
for extensions. It's discussed in [1].

I made patches to realize it. Although I have some TODOs,
I want to know your feedbacks. Please feel free to comment.


# Implementation of new APIs

I implemented 2 new APIs for extensions.
* RequestNamedExtensionWaitEventTranche()
* GetNamedExtensionWaitEventTranche()

Extensions can request custom wait events by calling
RequestNamedExtensionWaitEventTranche(). After that, use
GetNamedExtensionWaitEventTranche() to get the wait event information.

The APIs usage example by extensions are following.

```
shmem_request_hook = shmem_request;
shmem_startup_hook = shmem_startup;

static void
shmem_request(void)
{
/* request a custom wait event */
RequestNamedExtensionWaitEventTranche("custom_wait_event");
}

static void
shmem_startup(void)
{
/* get the wait event information */
	custom_wait_event = 
GetNamedExtensionWaitEventTranche("custom_wait_event");

}

void
extension_funtion()
{
(void) WaitLatch(MyLatch,
 WL_LATCH_SET | WL_TIMEOUT | 
WL_EXIT_ON_PM_DEATH,
 10L * 1000,
 custom_wait_event);  /* notify 
core with custom wait event */
ResetLatch(MyLatch);
}
```


# Implementation overview

I referenced the implementation of
RequestNamedLWLockTranche()/GetNamedLWLockTranche().
(0001-Support-to-define-custom-wait-events-for-extensions.patch)

Extensions calls RequestNamedExtensionWaitEventTranche() in
shmem_request_hook() to request wait events to be used by each 
extension.


In the core, the requested wait events are dynamically registered in 
shared

memory. The extension then obtains the wait event information with
GetNamedExtensionWaitEventTranche() and uses the value to notify the 
core

that it is waiting.

When a string representing of the wait event is requested,
it returns the name defined by calling 
RequestNamedExtensionWaitEventTranche().



# PoC extension

I created the PoC extension and you can use it, as shown here:
(0002-Add-a-extension-to-test-custom-wait-event.patch)

1. start PostgreSQL with the following configuration
shared_preload_libraries = 'inject_wait_event'

2. check wait events periodically
psql-1=# SELECT query, wait_event_type, wait_event FROM pg_stat_activity 
WHERE backend_type = 'client backend' AND pid != pg_backend_pid() ;

psql-1=# \watch

3. execute a function to inject a wait event
psql-2=# CREATE EXTENSION inject_wait_event;
psql-2=# SELECT inject_wait_event();

4. check the custom wait event
You can see the following results of psql-1.

(..snip..)

query| wait_event_type | wait_event
-+-+
 SELECT inject_wait_event(); | Extension   | Extension
(1 row)

(..snip..)

(...about 10 seconds later ..)


query| wait_event_type |wait_event
-+-+---
 SELECT inject_wait_event(); | Extension   | custom_wait_event   
 # requested wait event by the extension!

(1 row)

(..snip..)


# TODOs

* tests on windows (since I tested on Ubuntu 20.04 only)
* add custom wait events for existing contrib modules (ex. postgres_fdw)
* add regression code (but, it seems to be difficult)
* others? (Please let me know)


[1] 
https://www.postgresql.org/message-id/81290a48-b25c-22a5-31a6-3feff5864fe3%40gmail.com


Regards,

--
Masahiro Ikeda
NTT DATA CORPORATIONFrom 59a118402e5e59685fb9e0fb086872e25a405736 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda 
Date: Thu, 15 Jun 2023 12:57:29 +0900
Subject: [PATCH 2/3] Support to define custom wait events for extensions.

Currently, only one PG_WAIT_EXTENSION event can be used as a
wait event for extensions. Therefore, in environments with multiple
extensions are installed, it could take time to identify bottlenecks.

This commit allows defining custom wait events for extensions and
introduces a new API called RequestNamedExtensionWaitEventTranche()/
GetNamedExtensionWaitEventTranche().

These refer to RequestNamedLWLockTranche()/GetNamedLWLockTranche(),
but do not require as much flexibility as LWLock and can be implemented
more simply.

The extension calls RequestNamedExtensionWaitEventTranche() in
shmem_request_hook() to request wait events to be used by each extension.
In the core, the requested wait events are dynamically registered in shared
memory. The extension then obtains the wait event information with
GetNamedExtensionWaitEventTranche() and uses the value to notify the core
that it is waiting.
---
 src/backend/postmaster/postmaster.c |   6 +
 src/backen