aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/monitoring.sgml5
-rw-r--r--doc/src/sgml/xfunc.sgml26
-rw-r--r--src/backend/storage/lmgr/lwlocknames.txt1
-rw-r--r--src/backend/utils/activity/wait_event.c218
-rw-r--r--src/backend/utils/activity/wait_event_names.txt1
-rw-r--r--src/include/utils/wait_event.h18
-rw-r--r--src/test/modules/worker_spi/t/001_worker_spi.pl18
-rw-r--r--src/test/modules/worker_spi/worker_spi--1.0.sql5
-rw-r--r--src/test/modules/worker_spi/worker_spi.c109
-rw-r--r--src/tools/pgindent/typedefs.list2
10 files changed, 165 insertions, 238 deletions
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f4fc5d814fb..70511a2388e 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1121,9 +1121,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
<literal>LWLock</literal> types
to the list shown in <xref linkend="wait-event-extension-table"/> and
<xref linkend="wait-event-lwlock-table"/>. In some cases, the name
- assigned by an extension will not be available in all server processes;
- so an <literal>Extension</literal> or <literal>LWLock</literal> wait
- event might be reported as just
+ of <literal>LWLock</literal> assigned by an extension will not be
+ available in all server processes; It might be reported as just
<quote><literal>extension</literal></quote> rather than the
extension-assigned name.
</para>
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index d6345a775b6..281c178b0e8 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3454,33 +3454,15 @@ if (!ptr)
</sect2>
<sect2 id="xfunc-addin-wait-events">
- <title>Shared Memory and Custom Wait Events</title>
+ <title>Custom Wait Events</title>
<para>
Add-ins can define custom wait events under the wait event type
- <literal>Extension</literal>. The add-in's shared library must be
- preloaded by specifying it in <literal>shared_preload_libraries</literal>,
- and register a <literal>shmem_request_hook</literal> and a
- <literal>shmem_startup_hook</literal> in its
- <function>_PG_init</function> function.
- <literal>shmem_request_hook</literal> can request a shared memory size
- to be later used at startup by calling:
+ <literal>Extension</literal> by calling:
<programlisting>
-void RequestAddinShmemSpace(int size)
-</programlisting>
- </para>
- <para>
- <literal>shmem_startup_hook</literal> can allocate in shared memory
- custom wait events by calling while holding the LWLock
- <function>AddinShmemInitLock</function> to avoid any race conditions:
-<programlisting>
-uint32 WaitEventExtensionNew(void)
-</programlisting>
- Next, each process needs to associate the wait event allocated previously
- to a user-facing custom string, which is something done by calling:
-<programlisting>
-void WaitEventExtensionRegisterName(uint32 wait_event_info, const char *wait_event_name)
+uint32 WaitEventExtensionNew(const char *wait_event_name)
</programlisting>
+ The wait event is associated to a user-facing custom string.
An example can be found in <filename>src/test/modules/worker_spi</filename>
in the PostgreSQL source tree.
</para>
diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt
index b34b6afecde..811ad947420 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
WrapLimitsVacuumLock 46
NotifyQueueTailLock 47
+WaitEventExtensionLock 48
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index b3596ece80d..4b9b5c01cbe 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 = &local_my_wait_event_info;
#define WAIT_EVENT_CLASS_MASK 0xFF000000
#define WAIT_EVENT_ID_MASK 0x0000FFFF
+/*
+ * Hash tables for storing custom wait event ids and their names in
+ * shared memory.
+ *
+ * WaitEventExtensionHashById is used to find the name from a event id.
+ * Any backend can search it to find custom wait events.
+ *
+ * WaitEventExtensionHashByName is used to find the event ID from a name.
+ * It is used to ensure that no duplicated entries are registered.
+ *
+ * The size of the hash table is based on the assumption that
+ * WAIT_EVENT_EXTENSION_BASH_INIT_SIZE is enough for most cases, and it seems
+ * unlikely that the number of entries will reach
+ * WAIT_EVENT_EXTENSION_BASH_MAX_SIZE.
+ */
+static HTAB *WaitEventExtensionHashById; /* find names from IDs */
+static HTAB *WaitEventExtensionHashByName; /* find IDs from names */
+
+#define WAIT_EVENT_EXTENSION_HASH_INIT_SIZE 16
+#define WAIT_EVENT_EXTENSION_HASH_MAX_SIZE 128
+
+/* hash table entries */
+typedef struct WaitEventExtensionEntryById
+{
+ uint16 event_id; /* hash key */
+ char wait_event_name[NAMEDATALEN]; /* custom wait event name */
+} WaitEventExtensionEntryById;
+
+typedef struct WaitEventExtensionEntryByName
+{
+ char wait_event_name[NAMEDATALEN]; /* hash key */
+ uint16 event_id; /* wait event ID */
+} WaitEventExtensionEntryByName;
+
+
/* dynamic allocation counter for custom wait events in extensions */
typedef struct WaitEventExtensionCounterData
{
@@ -59,36 +94,39 @@ static WaitEventExtensionCounterData *WaitEventExtensionCounter;
#define NUM_BUILTIN_WAIT_EVENT_EXTENSION \
(WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - WAIT_EVENT_EXTENSION)
-/*
- * This is indexed by event ID minus NUM_BUILTIN_WAIT_EVENT_EXTENSION, and
- * stores the names of all dynamically-created event IDs known to the current
- * process. Any unused entries in the array will contain NULL.
- */
-static const char **WaitEventExtensionNames = NULL;
-static int WaitEventExtensionNamesAllocated = 0;
+/* wait event info for extensions */
+#define WAIT_EVENT_EXTENSION_INFO(eventId) (PG_WAIT_EXTENSION | eventId)
static const char *GetWaitEventExtensionIdentifier(uint16 eventId);
/*
- * Return the space for dynamic allocation counter.
+ * Return the space for dynamic shared hash tables and dynamic allocation counter.
*/
Size
WaitEventExtensionShmemSize(void)
{
- return sizeof(WaitEventExtensionCounterData);
+ Size sz;
+
+ sz = MAXALIGN(sizeof(WaitEventExtensionCounterData));
+ sz = add_size(sz, hash_estimate_size(WAIT_EVENT_EXTENSION_HASH_MAX_SIZE,
+ sizeof(WaitEventExtensionEntryById)));
+ sz = add_size(sz, hash_estimate_size(WAIT_EVENT_EXTENSION_HASH_MAX_SIZE,
+ sizeof(WaitEventExtensionEntryByName)));
+ return sz;
}
/*
- * Allocate shmem space for dynamic allocation counter.
+ * Allocate shmem space for dynamic shared hash and dynamic allocation counter.
*/
void
WaitEventExtensionShmemInit(void)
{
bool found;
+ HASHCTL info;
WaitEventExtensionCounter = (WaitEventExtensionCounterData *)
ShmemInitStruct("WaitEventExtensionCounterData",
- WaitEventExtensionShmemSize(), &found);
+ sizeof(WaitEventExtensionCounterData), &found);
if (!found)
{
@@ -96,21 +134,78 @@ WaitEventExtensionShmemInit(void)
WaitEventExtensionCounter->nextId = NUM_BUILTIN_WAIT_EVENT_EXTENSION;
SpinLockInit(&WaitEventExtensionCounter->mutex);
}
+
+ /* initialize or attach the hash tables to store custom wait events */
+ info.keysize = sizeof(uint16);
+ info.entrysize = sizeof(WaitEventExtensionEntryById);
+ WaitEventExtensionHashById = ShmemInitHash("WaitEventExtension hash by id",
+ WAIT_EVENT_EXTENSION_HASH_INIT_SIZE,
+ WAIT_EVENT_EXTENSION_HASH_MAX_SIZE,
+ &info,
+ HASH_ELEM | HASH_BLOBS);
+
+ /* key is a NULL-terminated string */
+ info.keysize = sizeof(char[NAMEDATALEN]);
+ info.entrysize = sizeof(WaitEventExtensionEntryByName);
+ WaitEventExtensionHashByName = ShmemInitHash("WaitEventExtension hash by name",
+ WAIT_EVENT_EXTENSION_HASH_INIT_SIZE,
+ WAIT_EVENT_EXTENSION_HASH_MAX_SIZE,
+ &info,
+ HASH_ELEM | HASH_STRINGS);
}
/*
- * Allocate a new event ID and return the wait event.
+ * Allocate a new event ID and return the wait event info.
+ *
+ * If the wait event name is already defined, this does not allocate a new
+ * entry; it returns the wait event information associated to the name.
*/
uint32
-WaitEventExtensionNew(void)
+WaitEventExtensionNew(const char *wait_event_name)
{
uint16 eventId;
+ bool found;
+ WaitEventExtensionEntryByName *entry_by_name;
+ WaitEventExtensionEntryById *entry_by_id;
+
+ /* Check the limit of the length of the event name */
+ if (strlen(wait_event_name) >= NAMEDATALEN)
+ elog(ERROR,
+ "cannot use custom wait event string longer than %u characters",
+ NAMEDATALEN - 1);
+
+ /*
+ * Check if the wait event info associated to the name is already defined,
+ * and return it if so.
+ */
+ LWLockAcquire(WaitEventExtensionLock, LW_SHARED);
+ entry_by_name = (WaitEventExtensionEntryByName *)
+ hash_search(WaitEventExtensionHashByName, wait_event_name,
+ HASH_FIND, &found);
+ LWLockRelease(WaitEventExtensionLock);
+ if (found)
+ return WAIT_EVENT_EXTENSION_INFO(entry_by_name->event_id);
- Assert(LWLockHeldByMeInMode(AddinShmemInitLock, LW_EXCLUSIVE));
+ /*
+ * Allocate and register a new wait event. Recheck if the event name
+ * exists, as it could be possible that a concurrent process has inserted
+ * one with the same name since the LWLock acquired again here was
+ * previously released.
+ */
+ LWLockAcquire(WaitEventExtensionLock, LW_EXCLUSIVE);
+ entry_by_name = (WaitEventExtensionEntryByName *)
+ hash_search(WaitEventExtensionHashByName, wait_event_name,
+ HASH_FIND, &found);
+ if (found)
+ {
+ LWLockRelease(WaitEventExtensionLock);
+ return WAIT_EVENT_EXTENSION_INFO(entry_by_name->event_id);
+ }
+ /* Allocate a new event Id */
SpinLockAcquire(&WaitEventExtensionCounter->mutex);
- if (WaitEventExtensionCounter->nextId > PG_UINT16_MAX)
+ if (WaitEventExtensionCounter->nextId >= WAIT_EVENT_EXTENSION_HASH_MAX_SIZE)
{
SpinLockRelease(&WaitEventExtensionCounter->mutex);
ereport(ERROR,
@@ -122,64 +217,23 @@ WaitEventExtensionNew(void)
SpinLockRelease(&WaitEventExtensionCounter->mutex);
- return PG_WAIT_EXTENSION | eventId;
-}
-
-/*
- * Register a dynamic wait event name for extension in the lookup table
- * of the current process.
- *
- * This routine will save a pointer to the wait event 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
-WaitEventExtensionRegisterName(uint32 wait_event_info,
- const char *wait_event_name)
-{
- uint32 classId;
- uint16 eventId;
-
- classId = wait_event_info & WAIT_EVENT_CLASS_MASK;
- eventId = wait_event_info & WAIT_EVENT_ID_MASK;
-
- /* Check the wait event class. */
- if (classId != PG_WAIT_EXTENSION)
- ereport(ERROR,
- errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid wait event class %u", classId));
-
- /* 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));
+ /* Register the new wait event */
+ entry_by_id = (WaitEventExtensionEntryById *)
+ hash_search(WaitEventExtensionHashById, &eventId,
+ HASH_ENTER, &found);
+ Assert(!found);
+ strlcpy(entry_by_id->wait_event_name, wait_event_name,
+ sizeof(entry_by_id->wait_event_name));
- /* Convert to array index. */
- eventId -= NUM_BUILTIN_WAIT_EVENT_EXTENSION;
+ entry_by_name = (WaitEventExtensionEntryByName *)
+ hash_search(WaitEventExtensionHashByName, wait_event_name,
+ HASH_ENTER, &found);
+ Assert(!found);
+ entry_by_name->event_id = eventId;
- /* If necessary, create or enlarge array. */
- if (eventId >= WaitEventExtensionNamesAllocated)
- {
- uint32 newalloc;
-
- newalloc = pg_nextpower2_32(Max(8, eventId + 1));
-
- if (WaitEventExtensionNames == NULL)
- WaitEventExtensionNames = (const char **)
- MemoryContextAllocZero(TopMemoryContext,
- newalloc * sizeof(char *));
- else
- WaitEventExtensionNames =
- repalloc0_array(WaitEventExtensionNames, const char *,
- WaitEventExtensionNamesAllocated, newalloc);
- WaitEventExtensionNamesAllocated = newalloc;
- }
+ LWLockRelease(WaitEventExtensionLock);
- WaitEventExtensionNames[eventId] = wait_event_name;
+ return WAIT_EVENT_EXTENSION_INFO(eventId);
}
/*
@@ -188,23 +242,25 @@ WaitEventExtensionRegisterName(uint32 wait_event_info,
static const char *
GetWaitEventExtensionIdentifier(uint16 eventId)
{
+ bool found;
+ WaitEventExtensionEntryById *entry;
+
/* Built-in event? */
if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
return "Extension";
- /*
- * It is a user-defined wait event, so look at WaitEventExtensionNames[].
- * However, it is possible that the name has never been registered by
- * calling WaitEventExtensionRegisterName() in the current process, in
- * which case give up and return "extension".
- */
- eventId -= NUM_BUILTIN_WAIT_EVENT_EXTENSION;
+ /* It is a user-defined wait event, so lookup hash table. */
+ LWLockAcquire(WaitEventExtensionLock, LW_SHARED);
+ entry = (WaitEventExtensionEntryById *)
+ hash_search(WaitEventExtensionHashById, &eventId,
+ HASH_FIND, &found);
+ LWLockRelease(WaitEventExtensionLock);
- if (eventId >= WaitEventExtensionNamesAllocated ||
- WaitEventExtensionNames[eventId] == NULL)
- return "extension";
+ if (!entry)
+ elog(ERROR, "could not find custom wait event name for ID %u",
+ eventId);
- return WaitEventExtensionNames[eventId];
+ return entry->wait_event_name;
}
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index fcd9d2c63cd..f9e01e33b13 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -317,6 +317,7 @@ WAIT_EVENT_DOCONLY LogicalRepWorker "Waiting to read or update the state of logi
WAIT_EVENT_DOCONLY XactTruncation "Waiting to execute <function>pg_xact_status</function> or update the oldest transaction ID available to it."
WAIT_EVENT_DOCONLY WrapLimitsVacuum "Waiting to update limits on transaction id and multixact consumption."
WAIT_EVENT_DOCONLY NotifyQueueTail "Waiting to update limit on <command>NOTIFY</command> message storage."
+WAIT_EVENT_DOCONLY WaitEventExtension "Waiting to read or update custom wait events information for extensions."
WAIT_EVENT_DOCONLY XactBuffer "Waiting for I/O on a transaction status SLRU buffer."
WAIT_EVENT_DOCONLY CommitTsBuffer "Waiting for I/O on a commit timestamp SLRU buffer."
diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index aad8bc08fa0..3eebdfad38b 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 to a string is already allocated, it returns the wait event
+ * information to use. If not, it gets one wait event ID allocated from
+ * a shared counter, associates the string to the ID in the shared dynamic
+ * hash and returns the wait event information.
+ *
+ * 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/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl
index c3e7f5fbe65..26b8a49beca 100644
--- a/src/test/modules/worker_spi/t/001_worker_spi.pl
+++ b/src/test/modules/worker_spi/t/001_worker_spi.pl
@@ -39,25 +39,11 @@ $node->poll_query_until('postgres',
$result = $node->safe_psql('postgres', 'SELECT * FROM schema4.counted;');
is($result, qq(total|1), 'dynamic bgworker correctly consumed tuple data');
-# Check the wait event used by the dynamic bgworker. For a session without
-# the state in shared memory known, the default of "extension" is the value
-# waited on.
+# Check the wait event used by the dynamic bgworker.
$result = $node->poll_query_until(
'postgres',
qq[SELECT wait_event FROM pg_stat_activity WHERE backend_type ~ 'worker_spi';],
- 'extension');
-is($result, 1, 'dynamic bgworker has reported "extension" as wait event');
-
-# If the shared memory state is loaded (here with worker_spi_init within
-# the same connection as the one querying pg_stat_activity), the wait
-# event is the custom one.
-# 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]);
+ qq[worker_spi_main]);
is($result, 1,
'dynamic bgworker has reported "worker_spi_main" as wait event');
diff --git a/src/test/modules/worker_spi/worker_spi--1.0.sql b/src/test/modules/worker_spi/worker_spi--1.0.sql
index f13f7e0f98d..e9d5b07373a 100644
--- a/src/test/modules/worker_spi/worker_spi--1.0.sql
+++ b/src/test/modules/worker_spi/worker_spi--1.0.sql
@@ -7,8 +7,3 @@ CREATE FUNCTION worker_spi_launch(pg_catalog.int4)
RETURNS pg_catalog.int4 STRICT
AS 'MODULE_PATHNAME'
LANGUAGE C;
-
-CREATE FUNCTION worker_spi_init()
-RETURNS VOID STRICT
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index c4317351ced..98f8d4194b2 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -44,33 +44,17 @@
PG_MODULE_MAGIC;
-PG_FUNCTION_INFO_V1(worker_spi_init);
PG_FUNCTION_INFO_V1(worker_spi_launch);
PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn();
-/* Shared memory state */
-typedef struct worker_spi_state
-{
- /* the wait event defined during initialization phase */
- uint32 wait_event;
-} worker_spi_state;
-
-static worker_spi_state *wsstate = NULL; /* pointer to shared memory */
-
-static shmem_request_hook_type prev_shmem_request_hook = NULL;
-static shmem_request_hook_type prev_shmem_startup_hook = NULL;
-
-static void worker_spi_shmem_request(void);
-static void worker_spi_shmem_startup(void);
-static void worker_spi_shmem_init(void);
-static Size worker_spi_memsize(void);
-
/* GUC variables */
static int worker_spi_naptime = 10;
static int worker_spi_total_workers = 2;
static char *worker_spi_database = NULL;
+/* value cached, fetched from shared memory */
+static uint32 worker_spi_wait_event_main = 0;
typedef struct worktable
{
@@ -78,63 +62,6 @@ typedef struct worktable
const char *name;
} worktable;
-static void
-worker_spi_shmem_request(void)
-{
- if (prev_shmem_request_hook)
- prev_shmem_request_hook();
-
- RequestAddinShmemSpace(worker_spi_memsize());
-}
-
-static void
-worker_spi_shmem_startup(void)
-{
- if (prev_shmem_startup_hook)
- prev_shmem_startup_hook();
-
- worker_spi_shmem_init();
-}
-
-static Size
-worker_spi_memsize(void)
-{
- return MAXALIGN(sizeof(worker_spi_state));
-}
-
-/*
- * Initialize the shared memory state of worker_spi.
- *
- * This routine allocates a new wait event when called the first time.
- * On follow-up calls, the name of the wait event associated with the
- * existing shared memory state is registered.
- */
-static void
-worker_spi_shmem_init(void)
-{
- bool found;
-
- wsstate = NULL;
-
- /* Create or attach to the shared memory state */
- LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
- wsstate = ShmemInitStruct("worker_spi State",
- sizeof(worker_spi_state),
- &found);
-
- /* Define a new wait event */
- if (!found)
- wsstate->wait_event = WaitEventExtensionNew();
-
- LWLockRelease(AddinShmemInitLock);
-
- /*
- * Register the wait event in the lookup table of the current process.
- */
- WaitEventExtensionRegisterName(wsstate->wait_event, "worker_spi_main");
- return;
-}
-
/*
* Initialize workspace for a worker process: create the schema if it doesn't
* already exist.
@@ -224,9 +151,6 @@ worker_spi_main(Datum main_arg)
/* We're now ready to receive signals */
BackgroundWorkerUnblockSignals();
- /* Create (if necessary) and attach to our shared memory area. */
- worker_spi_shmem_init();
-
/* Connect to our database */
BackgroundWorkerInitializeConnection(worker_spi_database, NULL, 0);
@@ -268,6 +192,10 @@ worker_spi_main(Datum main_arg)
{
int ret;
+ /* First time, allocate or get the custom wait event */
+ if (worker_spi_wait_event_main == 0)
+ worker_spi_wait_event_main = WaitEventExtensionNew("worker_spi_main");
+
/*
* Background workers mustn't call usleep() or any direct equivalent:
* instead, they may wait on their process latch, which sleeps as
@@ -277,7 +205,7 @@ worker_spi_main(Datum main_arg)
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
worker_spi_naptime * 1000L,
- wsstate->wait_event);
+ worker_spi_wait_event_main);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
@@ -406,11 +334,6 @@ _PG_init(void)
MarkGUCPrefixReserved("worker_spi");
- prev_shmem_request_hook = shmem_request_hook;
- shmem_request_hook = worker_spi_shmem_request;
- prev_shmem_startup_hook = shmem_startup_hook;
- shmem_startup_hook = worker_spi_shmem_startup;
-
/* set up common data for all our workers */
memset(&worker, 0, sizeof(worker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
@@ -435,21 +358,6 @@ _PG_init(void)
}
/*
- * Wrapper to initialize a session with the shared memory state
- * used by this module. This is a convenience routine to be able to
- * see the custom wait event stored in shared memory without loading
- * through shared_preload_libraries.
- */
-Datum
-worker_spi_init(PG_FUNCTION_ARGS)
-{
- /* Create (if necessary) and attach to our shared memory area. */
- worker_spi_shmem_init();
-
- PG_RETURN_VOID();
-}
-
-/*
* Dynamically launch an SPI worker.
*/
Datum
@@ -461,9 +369,6 @@ worker_spi_launch(PG_FUNCTION_ARGS)
BgwHandleStatus status;
pid_t pid;
- /* Create (if necessary) and attach to our shared memory area. */
- worker_spi_shmem_init();
-
memset(&worker, 0, sizeof(worker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 52a8789cc4d..51b7951ad84 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2993,6 +2993,8 @@ WaitEventBufferPin
WaitEventClient
WaitEventExtension
WaitEventExtensionCounterData
+WaitEventExtensionEntryById
+WaitEventExtensionEntryByName
WaitEventIO
WaitEventIPC
WaitEventSet