Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc9af054

Browse files
committed
Support custom wait events for wait event type "Extension"
Two backend routines are added to allow extension to allocate and definecustom wait events, all of these being allocated in the type"Extension":* WaitEventExtensionNew(), that allocates a wait event ID computed froma counter in shared memory.* WaitEventExtensionRegisterName(), to associate a custom string to thewait event ID allocated.Note that this includes an example of how to use this new facility inworker_spi with tests in TAP for various scenarios, and somedocumentation about how to use them.Any code in the tree that currently uses WAIT_EVENT_EXTENSION couldswitch to this new facility to define custom wait events. This is leftas work for future patches.Author: Masahiro IkedaReviewed-by: Andres Freund, Michael Paquier, Tristan Partin, BharathRupireddyDiscussion:https://postgr.es/m/b9f5411acda0cf15c8fbb767702ff43e@oss.nttdata.com
1 parent39055cb commitc9af054

File tree

11 files changed

+393
-23
lines changed

11 files changed

+393
-23
lines changed

‎doc/src/sgml/monitoring.sgml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,11 +1117,14 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
11171117

11181118
<note>
11191119
<para>
1120-
Extensions can add <literal>LWLock</literal> types to the list shown in
1121-
<xref linkend="wait-event-lwlock-table"/>. In some cases, the name
1120+
Extensions can add <literal>Extension</literal> and
1121+
<literal>LWLock</literal> types
1122+
to the list shown in <xref linkend="wait-event-extension-table"/> and
1123+
<xref linkend="wait-event-lwlock-table"/>. In some cases, the name
11221124
assigned by an extension will not be available in all server processes;
1123-
so an <literal>LWLock</literal> wait event might be reported as
1124-
just <quote><literal>extension</literal></quote> rather than the
1125+
so an <literal>Extension</literal> or <literal>LWLock</literal> wait
1126+
event might be reported as just
1127+
<quote><literal>extension</literal></quote> rather than the
11251128
extension-assigned name.
11261129
</para>
11271130
</note>

‎doc/src/sgml/xfunc.sgml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3453,6 +3453,51 @@ if (!ptr)
34533453
</para>
34543454
</sect2>
34553455

3456+
<sect2 id="xfunc-addin-wait-events">
3457+
<title>Shared Memory and Custom Wait Events</title>
3458+
3459+
<para>
3460+
Add-ins can define custom wait events under the wait event type
3461+
<literal>Extension</literal>. The add-in's shared library must be
3462+
preloaded by specifying it in <literal>shared_preload_libraries</literal>,
3463+
and register a <literal>shmem_request_hook</literal> and a
3464+
<literal>shmem_startup_hook</literal> in its
3465+
<function>_PG_init</function> function.
3466+
<literal>shmem_request_hook</literal> can request a shared memory size
3467+
to be later used at startup by calling:
3468+
<programlisting>
3469+
void RequestAddinShmemSpace(int size)
3470+
</programlisting>
3471+
</para>
3472+
<para>
3473+
<literal>shmem_startup_hook</literal> can allocate in shared memory
3474+
custom wait events by calling while holding the LWLock
3475+
<function>AddinShmemInitLock</function> to avoid any race conditions:
3476+
<programlisting>
3477+
uint32 WaitEventExtensionNew(void)
3478+
</programlisting>
3479+
Next, each process needs to associate the wait event allocated previously
3480+
to a user-facing custom string, which is something done by calling:
3481+
<programlisting>
3482+
void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name)
3483+
</programlisting>
3484+
An example can be found in <filename>src/test/modules/worker_spi</filename>
3485+
in the PostgreSQL source tree.
3486+
</para>
3487+
<para>
3488+
Custom wait events can be viewed in
3489+
<link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>:
3490+
<screen>
3491+
=# SELECT wait_event_type, wait_event FROM pg_stat_activity
3492+
WHERE backend_type ~ 'worker_spi';
3493+
wait_event_type | wait_event
3494+
-----------------+-----------------
3495+
Extension | worker_spi_main
3496+
(1 row)
3497+
</screen>
3498+
</para>
3499+
</sect2>
3500+
34563501
<sect2 id="extend-cpp">
34573502
<title>Using C++ for Extensibility</title>
34583503

‎src/backend/storage/ipc/ipci.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include"storage/spin.h"
5050
#include"utils/guc.h"
5151
#include"utils/snapmgr.h"
52+
#include"utils/wait_event.h"
5253

5354
/* GUCs */
5455
intshared_memory_type=DEFAULT_SHARED_MEMORY_TYPE;
@@ -142,6 +143,7 @@ CalculateShmemSize(int *num_semaphores)
142143
size=add_size(size,SyncScanShmemSize());
143144
size=add_size(size,AsyncShmemSize());
144145
size=add_size(size,StatsShmemSize());
146+
size=add_size(size,WaitEventExtensionShmemSize());
145147
#ifdefEXEC_BACKEND
146148
size=add_size(size,ShmemBackendArraySize());
147149
#endif
@@ -301,6 +303,7 @@ CreateSharedMemoryAndSemaphores(void)
301303
SyncScanShmemInit();
302304
AsyncShmemInit();
303305
StatsShmemInit();
306+
WaitEventExtensionShmemInit();
304307

305308
#ifdefEXEC_BACKEND
306309

‎src/backend/utils/activity/generate-wait_event_types.pl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@
133133
foreachmy$waitclass (sort {uc($a)cmpuc($b) }keys%hashwe)
134134
{
135135

136-
# Don't generate .c and .h files forLWLock and Lock, these are
137-
# handled independently.
136+
# Don't generate .c and .h files forExtension, LWLock and
137+
#Lock, these arehandled independently.
138138
next
139-
if ($waitclasseq'WaitEventLWLock'
139+
if ($waitclasseq'WaitEventExtension'
140+
||$waitclasseq'WaitEventLWLock'
140141
||$waitclasseq'WaitEventLock');
141142

142143
my$last =$waitclass;

‎src/backend/utils/activity/wait_event.c

Lines changed: 170 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@
2222
*/
2323
#include"postgres.h"
2424

25+
#include"miscadmin.h"
26+
#include"port/pg_bitutils.h"
2527
#include"storage/lmgr.h"/* for GetLockNameFromTagType */
2628
#include"storage/lwlock.h"/* for GetLWLockIdentifier */
29+
#include"storage/spin.h"
30+
#include"utils/memutils.h"
2731
#include"utils/wait_event.h"
2832

2933

3034
staticconstchar*pgstat_get_wait_activity(WaitEventActivityw);
3135
staticconstchar*pgstat_get_wait_bufferpin(WaitEventBufferPinw);
3236
staticconstchar*pgstat_get_wait_client(WaitEventClientw);
33-
staticconstchar*pgstat_get_wait_extension(WaitEventExtensionw);
3437
staticconstchar*pgstat_get_wait_ipc(WaitEventIPCw);
3538
staticconstchar*pgstat_get_wait_timeout(WaitEventTimeoutw);
3639
staticconstchar*pgstat_get_wait_io(WaitEventIOw);
@@ -42,6 +45,169 @@ uint32 *my_wait_event_info = &local_my_wait_event_info;
4245
#defineWAIT_EVENT_CLASS_MASK0xFF000000
4346
#defineWAIT_EVENT_ID_MASK0x0000FFFF
4447

48+
/* dynamic allocation counter for custom wait events in extensions */
49+
typedefstructWaitEventExtensionCounterData
50+
{
51+
intnextId;/* next ID to assign */
52+
slock_tmutex;/* protects the counter */
53+
}WaitEventExtensionCounterData;
54+
55+
/* pointer to the shared memory */
56+
staticWaitEventExtensionCounterData*WaitEventExtensionCounter;
57+
58+
/* first event ID of custom wait events for extensions */
59+
#defineNUM_BUILTIN_WAIT_EVENT_EXTENSION\
60+
(WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - WAIT_EVENT_EXTENSION)
61+
62+
/*
63+
* This is indexed by event ID minus NUM_BUILTIN_WAIT_EVENT_EXTENSION, and
64+
* stores the names of all dynamically-created event IDs known to the current
65+
* process. Any unused entries in the array will contain NULL.
66+
*/
67+
staticconstchar**WaitEventExtensionNames=NULL;
68+
staticintWaitEventExtensionNamesAllocated=0;
69+
70+
staticconstchar*GetWaitEventExtensionIdentifier(uint16eventId);
71+
72+
/*
73+
* Return the space for dynamic allocation counter.
74+
*/
75+
Size
76+
WaitEventExtensionShmemSize(void)
77+
{
78+
returnsizeof(WaitEventExtensionCounterData);
79+
}
80+
81+
/*
82+
* Allocate shmem space for dynamic allocation counter.
83+
*/
84+
void
85+
WaitEventExtensionShmemInit(void)
86+
{
87+
boolfound;
88+
89+
WaitEventExtensionCounter= (WaitEventExtensionCounterData*)
90+
ShmemInitStruct("WaitEventExtensionCounterData",
91+
WaitEventExtensionShmemSize(),&found);
92+
93+
if (!found)
94+
{
95+
/* initialize the allocation counter and its spinlock. */
96+
WaitEventExtensionCounter->nextId=NUM_BUILTIN_WAIT_EVENT_EXTENSION;
97+
SpinLockInit(&WaitEventExtensionCounter->mutex);
98+
}
99+
}
100+
101+
/*
102+
* Allocate a new event ID and return the wait event.
103+
*/
104+
uint32
105+
WaitEventExtensionNew(void)
106+
{
107+
uint16eventId;
108+
109+
Assert(LWLockHeldByMeInMode(AddinShmemInitLock,LW_EXCLUSIVE));
110+
111+
SpinLockAcquire(&WaitEventExtensionCounter->mutex);
112+
113+
if (WaitEventExtensionCounter->nextId>PG_UINT16_MAX)
114+
{
115+
SpinLockRelease(&WaitEventExtensionCounter->mutex);
116+
ereport(ERROR,
117+
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
118+
errmsg("too many wait events for extensions"));
119+
}
120+
121+
eventId=WaitEventExtensionCounter->nextId++;
122+
123+
SpinLockRelease(&WaitEventExtensionCounter->mutex);
124+
125+
returnPG_WAIT_EXTENSION |eventId;
126+
}
127+
128+
/*
129+
* Register a dynamic wait event name for extension in the lookup table
130+
* of the current process.
131+
*
132+
* This routine will save a pointer to the wait event name passed as an argument,
133+
* so the name should be allocated in a backend-lifetime context
134+
* (shared memory, TopMemoryContext, static constant, or similar).
135+
*
136+
* The "wait_event_name" will be user-visible as a wait event name, so try to
137+
* use a name that fits the style for those.
138+
*/
139+
void
140+
WaitEventExtensionRegisterName(uint32wait_event_info,
141+
constchar*wait_event_name)
142+
{
143+
uint32classId;
144+
uint16eventId;
145+
146+
classId=wait_event_info&WAIT_EVENT_CLASS_MASK;
147+
eventId=wait_event_info&WAIT_EVENT_ID_MASK;
148+
149+
/* Check the wait event class. */
150+
if (classId!=PG_WAIT_EXTENSION)
151+
ereport(ERROR,
152+
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
153+
errmsg("invalid wait event class %u",classId));
154+
155+
/* This should only be called for user-defined wait event. */
156+
if (eventId<NUM_BUILTIN_WAIT_EVENT_EXTENSION)
157+
ereport(ERROR,
158+
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
159+
errmsg("invalid wait event ID %u",eventId));
160+
161+
/* Convert to array index. */
162+
eventId-=NUM_BUILTIN_WAIT_EVENT_EXTENSION;
163+
164+
/* If necessary, create or enlarge array. */
165+
if (eventId >=WaitEventExtensionNamesAllocated)
166+
{
167+
uint32newalloc;
168+
169+
newalloc=pg_nextpower2_32(Max(8,eventId+1));
170+
171+
if (WaitEventExtensionNames==NULL)
172+
WaitEventExtensionNames= (constchar**)
173+
MemoryContextAllocZero(TopMemoryContext,
174+
newalloc*sizeof(char*));
175+
else
176+
WaitEventExtensionNames=
177+
repalloc0_array(WaitEventExtensionNames,constchar*,
178+
WaitEventExtensionNamesAllocated,newalloc);
179+
WaitEventExtensionNamesAllocated=newalloc;
180+
}
181+
182+
WaitEventExtensionNames[eventId]=wait_event_name;
183+
}
184+
185+
/*
186+
* Return the name of an wait event ID for extension.
187+
*/
188+
staticconstchar*
189+
GetWaitEventExtensionIdentifier(uint16eventId)
190+
{
191+
/* Built-in event? */
192+
if (eventId<NUM_BUILTIN_WAIT_EVENT_EXTENSION)
193+
return"Extension";
194+
195+
/*
196+
* It is a user-defined wait event, so look at WaitEventExtensionNames[].
197+
* However, it is possible that the name has never been registered by
198+
* calling WaitEventExtensionRegisterName() in the current process, in
199+
* which case give up and return "extension".
200+
*/
201+
eventId-=NUM_BUILTIN_WAIT_EVENT_EXTENSION;
202+
203+
if (eventId >=WaitEventExtensionNamesAllocated||
204+
WaitEventExtensionNames[eventId]==NULL)
205+
return"extension";
206+
207+
returnWaitEventExtensionNames[eventId];
208+
}
209+
210+
45211
/*
46212
* Configure wait event reporting to report wait events to *wait_event_info.
47213
* *wait_event_info needs to be valid until pgstat_reset_wait_event_storage()
@@ -151,6 +317,9 @@ pgstat_get_wait_event(uint32 wait_event_info)
151317
casePG_WAIT_LOCK:
152318
event_name=GetLockNameFromTagType(eventId);
153319
break;
320+
casePG_WAIT_EXTENSION:
321+
event_name=GetWaitEventExtensionIdentifier(eventId);
322+
break;
154323
casePG_WAIT_BUFFERPIN:
155324
{
156325
WaitEventBufferPinw= (WaitEventBufferPin)wait_event_info;
@@ -172,13 +341,6 @@ pgstat_get_wait_event(uint32 wait_event_info)
172341
event_name=pgstat_get_wait_client(w);
173342
break;
174343
}
175-
casePG_WAIT_EXTENSION:
176-
{
177-
WaitEventExtensionw= (WaitEventExtension)wait_event_info;
178-
179-
event_name=pgstat_get_wait_extension(w);
180-
break;
181-
}
182344
casePG_WAIT_IPC:
183345
{
184346
WaitEventIPCw= (WaitEventIPC)wait_event_info;

‎src/backend/utils/activity/wait_event_names.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ WAIT_EVENT_BUFFER_PINBufferPin"Waiting to acquire an exclusive pin on a buffer
261261

262262
Section: ClassName - WaitEventExtension
263263

264-
WAIT_EVENT_EXTENSIONExtension"Waiting in an extension."
264+
WAIT_EVENT_DOCONLYExtension"Waiting in an extension."
265265

266266
#
267267
# Wait events - LWLock

‎src/include/utils/wait_event.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,32 @@ extern void pgstat_reset_wait_event_storage(void);
3838
externPGDLLIMPORTuint32*my_wait_event_info;
3939

4040

41+
/* ----------
42+
* Wait Events - Extension
43+
*
44+
* Use this category when the server process is waiting for some condition
45+
* defined by an extension module.
46+
*
47+
* Extensions can define their own wait events in this category. First,
48+
* they should call WaitEventExtensionNew() to get one or more wait event
49+
* IDs that are allocated from a shared counter. These can be used directly
50+
* with pgstat_report_wait_start() or equivalent. Next, each individual
51+
* process should call WaitEventExtensionRegisterName() to associate a wait
52+
* event string to the number allocated previously.
53+
*/
54+
typedefenum
55+
{
56+
WAIT_EVENT_EXTENSION=PG_WAIT_EXTENSION,
57+
WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED
58+
}WaitEventExtension;
59+
60+
externvoidWaitEventExtensionShmemInit(void);
61+
externSizeWaitEventExtensionShmemSize(void);
62+
63+
externuint32WaitEventExtensionNew(void);
64+
externvoidWaitEventExtensionRegisterName(uint32wait_event_info,
65+
constchar*wait_event_name);
66+
4167
/* ----------
4268
* pgstat_report_wait_start() -
4369
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp