From af720b4c50a122647182f4a030bb0ea8f750fe2f Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 14 Aug 2023 14:47:27 +0900 Subject: [PATCH] Change custom wait events to use dynamic shared hash tables Currently, the names of the custom wait event must be registered for each backend, requiring all these to link to the shared memory area of an extension, even if these are not loaded with shared_preload_libraries. This patch relaxes the constraints related to this infrastructure by storing the wait events and their names in two dynamic hash tables in shared memory. This has the advantage to simplify the registration of custom wait events to a single routine call that returns an event ID ready for consumption: uint32 WaitEventExtensionNew(const char *wait_event_name); The caller of this routine can then cache locally the ID returned, to be used for pgstat_report_wait_start(), WaitLatch() or a similar routine. The implementation uses two hash tables: one with a key based on the event name to avoid duplicates and a second using the event ID as key for event lookups, like on pg_stat_activity. These tables can hold a minimum of 16 entries, and a maximum of 128 entries, which should be plenty enough. The code changes done in worker_spi show how things are simplified (most of the code removed in this commit comes from there): - worker_spi_init() is gone. - No more shared memory hooks required (size requested and initialization). - 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, with a few tweaks from me. Discussion: https://postgr.es/m/20230801032349.aaiuvhtrcvvcwzcx@awork3.anarazel.de --- doc/src/sgml/monitoring.sgml | 5 +- doc/src/sgml/xfunc.sgml | 26 +-- src/backend/storage/lmgr/lwlocknames.txt | 1 + src/backend/utils/activity/wait_event.c | 218 +++++++++++++++--------- src/backend/utils/activity/wait_event_names.txt | 1 + src/include/utils/wait_event.h | 18 +- src/test/modules/worker_spi/t/001_worker_spi.pl | 18 +- src/test/modules/worker_spi/worker_spi--1.0.sql | 5 - src/test/modules/worker_spi/worker_spi.c | 109 +----------- src/tools/pgindent/typedefs.list | 2 + 10 files changed, 165 insertions(+), 238 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index f4fc5d814f..70511a2388 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 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 + of LWLock assigned by an extension will not be + available in all server processes; It 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 - shmem_startup_hook in its - _PG_init function. - shmem_request_hook can request a shared memory size - to be later used at startup by calling: + Extension by calling: -void RequestAddinShmemSpace(int size) - - - - shmem_startup_hook can allocate in 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..811ad94742 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 b3596ece80..4b9b5c01cb 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 fcd9d2c63c..f9e01e33b1 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 pg_xact_status 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 NOTIFY 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 aad8bc08fa..3eebdfad38 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 c3e7f5fbe6..26b8a49bec 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 f13f7e0f98..e9d5b07373 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 c4317351ce..98f8d4194b 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 52a8789cc4..51b7951ad8 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 -- 2.11.4.GIT