Add background worker type
Add bgw_type field to background worker structure. It is intended to be set to the same value for all workers of the same type, so they can be grouped in pg_stat_activity, for example. The backend_type column in pg_stat_activity now shows bgw_type for a background worker. The ps listing also no longer calls out that a process is a background worker but just show the bgw_type. That way, being a background worker is more of an implementation detail now that is not shown to the user. However, most log messages still refer to 'background worker "%s"'; otherwise constructing sensible and translatable log messages would become tricky. Reviewed-by: Michael Paquier <michael.paquier@gmail.com> Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
This commit is contained in:
parent
8b304b8b72
commit
5373bc2a08
@ -800,7 +800,8 @@ apw_start_master_worker(void)
|
|||||||
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
||||||
strcpy(worker.bgw_library_name, "pg_prewarm");
|
strcpy(worker.bgw_library_name, "pg_prewarm");
|
||||||
strcpy(worker.bgw_function_name, "autoprewarm_main");
|
strcpy(worker.bgw_function_name, "autoprewarm_main");
|
||||||
strcpy(worker.bgw_name, "autoprewarm");
|
strcpy(worker.bgw_name, "autoprewarm master");
|
||||||
|
strcpy(worker.bgw_type, "autoprewarm master");
|
||||||
|
|
||||||
if (process_shared_preload_libraries_in_progress)
|
if (process_shared_preload_libraries_in_progress)
|
||||||
{
|
{
|
||||||
@ -840,7 +841,8 @@ apw_start_database_worker(void)
|
|||||||
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
||||||
strcpy(worker.bgw_library_name, "pg_prewarm");
|
strcpy(worker.bgw_library_name, "pg_prewarm");
|
||||||
strcpy(worker.bgw_function_name, "autoprewarm_database_main");
|
strcpy(worker.bgw_function_name, "autoprewarm_database_main");
|
||||||
strcpy(worker.bgw_name, "autoprewarm");
|
strcpy(worker.bgw_name, "autoprewarm worker");
|
||||||
|
strcpy(worker.bgw_type, "autoprewarm worker");
|
||||||
|
|
||||||
/* must set notify PID to wait for shutdown */
|
/* must set notify PID to wait for shutdown */
|
||||||
worker.bgw_notify_pid = MyProcPid;
|
worker.bgw_notify_pid = MyProcPid;
|
||||||
|
@ -51,6 +51,7 @@ typedef void (*bgworker_main_type)(Datum main_arg);
|
|||||||
typedef struct BackgroundWorker
|
typedef struct BackgroundWorker
|
||||||
{
|
{
|
||||||
char bgw_name[BGW_MAXLEN];
|
char bgw_name[BGW_MAXLEN];
|
||||||
|
char bgw_type[BGW_MAXLEN];
|
||||||
int bgw_flags;
|
int bgw_flags;
|
||||||
BgWorkerStartTime bgw_start_time;
|
BgWorkerStartTime bgw_start_time;
|
||||||
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
|
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
|
||||||
@ -64,8 +65,14 @@ typedef struct BackgroundWorker
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<structfield>bgw_name</> is a string to be used in log messages, process
|
<structfield>bgw_name</> and <structfield>bgw_type</structfield> are
|
||||||
listings and similar contexts.
|
strings to be used in log messages, process listings and similar contexts.
|
||||||
|
<structfield>bgw_type</structfield> should be the same for all background
|
||||||
|
workers of the same type, so that it is possible to group such workers in a
|
||||||
|
process listing, for example. <structfield>bgw_name</structfield> on the
|
||||||
|
other hand can contain additional information about the specific process.
|
||||||
|
(Typically, the string for <structfield>bgw_name</structfield> will contain
|
||||||
|
the type somehow, but that is not strictly required.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -467,6 +467,7 @@ LaunchParallelWorkers(ParallelContext *pcxt)
|
|||||||
memset(&worker, 0, sizeof(worker));
|
memset(&worker, 0, sizeof(worker));
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
|
snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
|
||||||
MyProcPid);
|
MyProcPid);
|
||||||
|
snprintf(worker.bgw_type, BGW_MAXLEN, "parallel worker");
|
||||||
worker.bgw_flags =
|
worker.bgw_flags =
|
||||||
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
|
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
|
||||||
| BGWORKER_CLASS_PARALLEL;
|
| BGWORKER_CLASS_PARALLEL;
|
||||||
|
@ -344,6 +344,8 @@ BackgroundWorkerStateChange(void)
|
|||||||
*/
|
*/
|
||||||
ascii_safe_strlcpy(rw->rw_worker.bgw_name,
|
ascii_safe_strlcpy(rw->rw_worker.bgw_name,
|
||||||
slot->worker.bgw_name, BGW_MAXLEN);
|
slot->worker.bgw_name, BGW_MAXLEN);
|
||||||
|
ascii_safe_strlcpy(rw->rw_worker.bgw_type,
|
||||||
|
slot->worker.bgw_type, BGW_MAXLEN);
|
||||||
ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
|
ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
|
||||||
slot->worker.bgw_library_name, BGW_MAXLEN);
|
slot->worker.bgw_library_name, BGW_MAXLEN);
|
||||||
ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
|
ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
|
||||||
@ -630,6 +632,12 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If bgw_type is not filled in, use bgw_name.
|
||||||
|
*/
|
||||||
|
if (strcmp(worker->bgw_type, "") == 0)
|
||||||
|
strcpy(worker->bgw_type, worker->bgw_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,7 +679,7 @@ bgworker_die(SIGNAL_ARGS)
|
|||||||
ereport(FATAL,
|
ereport(FATAL,
|
||||||
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
(errcode(ERRCODE_ADMIN_SHUTDOWN),
|
||||||
errmsg("terminating background worker \"%s\" due to administrator command",
|
errmsg("terminating background worker \"%s\" due to administrator command",
|
||||||
MyBgworkerEntry->bgw_name)));
|
MyBgworkerEntry->bgw_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -700,7 +708,6 @@ void
|
|||||||
StartBackgroundWorker(void)
|
StartBackgroundWorker(void)
|
||||||
{
|
{
|
||||||
sigjmp_buf local_sigjmp_buf;
|
sigjmp_buf local_sigjmp_buf;
|
||||||
char buf[MAXPGPATH];
|
|
||||||
BackgroundWorker *worker = MyBgworkerEntry;
|
BackgroundWorker *worker = MyBgworkerEntry;
|
||||||
bgworker_main_type entrypt;
|
bgworker_main_type entrypt;
|
||||||
|
|
||||||
@ -710,8 +717,7 @@ StartBackgroundWorker(void)
|
|||||||
IsBackgroundWorker = true;
|
IsBackgroundWorker = true;
|
||||||
|
|
||||||
/* Identify myself via ps */
|
/* Identify myself via ps */
|
||||||
snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
|
init_ps_display(worker->bgw_name, "", "", "");
|
||||||
init_ps_display(buf, "", "", "");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're not supposed to have shared memory access, then detach from
|
* If we're not supposed to have shared memory access, then detach from
|
||||||
@ -1233,3 +1239,40 @@ LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname)
|
|||||||
return (bgworker_main_type)
|
return (bgworker_main_type)
|
||||||
load_external_function(libraryname, funcname, true, NULL);
|
load_external_function(libraryname, funcname, true, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a PID, get the bgw_type of the background worker. Returns NULL if
|
||||||
|
* not a valid background worker.
|
||||||
|
*
|
||||||
|
* The return value is in static memory belonging to this function, so it has
|
||||||
|
* to be used before calling this function again. This is so that the caller
|
||||||
|
* doesn't have to worry about the background worker locking protocol.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
GetBackgroundWorkerTypeByPid(pid_t pid)
|
||||||
|
{
|
||||||
|
int slotno;
|
||||||
|
bool found = false;
|
||||||
|
static char result[BGW_MAXLEN];
|
||||||
|
|
||||||
|
LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
|
||||||
|
|
||||||
|
for (slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
|
||||||
|
{
|
||||||
|
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
|
||||||
|
|
||||||
|
if (slot->pid > 0 && slot->pid == pid)
|
||||||
|
{
|
||||||
|
strcpy(result, slot->worker.bgw_type);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LWLockRelease(BackgroundWorkerLock);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -3117,8 +3117,9 @@ CleanupBackgroundWorker(int pid,
|
|||||||
exitstatus = 0;
|
exitstatus = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(namebuf, MAXPGPATH, "%s: %s", _("worker process"),
|
snprintf(namebuf, MAXPGPATH, _("background worker \"%s\""),
|
||||||
rw->rw_worker.bgw_name);
|
rw->rw_worker.bgw_type);
|
||||||
|
|
||||||
|
|
||||||
if (!EXIT_STATUS_0(exitstatus))
|
if (!EXIT_STATUS_0(exitstatus))
|
||||||
{
|
{
|
||||||
|
@ -422,6 +422,7 @@ retry:
|
|||||||
else
|
else
|
||||||
snprintf(bgw.bgw_name, BGW_MAXLEN,
|
snprintf(bgw.bgw_name, BGW_MAXLEN,
|
||||||
"logical replication worker for subscription %u", subid);
|
"logical replication worker for subscription %u", subid);
|
||||||
|
snprintf(bgw.bgw_type, BGW_MAXLEN, "logical replication worker");
|
||||||
|
|
||||||
bgw.bgw_restart_time = BGW_NEVER_RESTART;
|
bgw.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
bgw.bgw_notify_pid = MyProcPid;
|
bgw.bgw_notify_pid = MyProcPid;
|
||||||
@ -775,6 +776,8 @@ ApplyLauncherRegister(void)
|
|||||||
snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
|
snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
|
||||||
snprintf(bgw.bgw_name, BGW_MAXLEN,
|
snprintf(bgw.bgw_name, BGW_MAXLEN,
|
||||||
"logical replication launcher");
|
"logical replication launcher");
|
||||||
|
snprintf(bgw.bgw_type, BGW_MAXLEN,
|
||||||
|
"logical replication launcher");
|
||||||
bgw.bgw_restart_time = 5;
|
bgw.bgw_restart_time = 5;
|
||||||
bgw.bgw_notify_pid = 0;
|
bgw.bgw_notify_pid = 0;
|
||||||
bgw.bgw_main_arg = (Datum) 0;
|
bgw.bgw_main_arg = (Datum) 0;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "funcapi.h"
|
#include "funcapi.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
|
#include "postmaster/bgworker_internals.h"
|
||||||
#include "postmaster/postmaster.h"
|
#include "postmaster/postmaster.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
#include "storage/procarray.h"
|
#include "storage/procarray.h"
|
||||||
@ -823,8 +824,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Add backend type */
|
/* Add backend type */
|
||||||
values[17] =
|
if (beentry->st_backendType == B_BG_WORKER)
|
||||||
CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
|
{
|
||||||
|
const char *bgw_type;
|
||||||
|
|
||||||
|
bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid);
|
||||||
|
if (bgw_type)
|
||||||
|
values[17] = CStringGetTextDatum(bgw_type);
|
||||||
|
else
|
||||||
|
nulls[17] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
values[17] =
|
||||||
|
CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,7 @@ typedef enum
|
|||||||
typedef struct BackgroundWorker
|
typedef struct BackgroundWorker
|
||||||
{
|
{
|
||||||
char bgw_name[BGW_MAXLEN];
|
char bgw_name[BGW_MAXLEN];
|
||||||
|
char bgw_type[BGW_MAXLEN];
|
||||||
int bgw_flags;
|
int bgw_flags;
|
||||||
BgWorkerStartTime bgw_start_time;
|
BgWorkerStartTime bgw_start_time;
|
||||||
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
|
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
|
||||||
@ -122,6 +123,7 @@ extern BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle,
|
|||||||
extern BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pid);
|
extern BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pid);
|
||||||
extern BgwHandleStatus
|
extern BgwHandleStatus
|
||||||
WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *);
|
WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *);
|
||||||
|
extern const char *GetBackgroundWorkerTypeByPid(pid_t pid);
|
||||||
|
|
||||||
/* Terminate a bgworker */
|
/* Terminate a bgworker */
|
||||||
extern void TerminateBackgroundWorker(BackgroundWorkerHandle *handle);
|
extern void TerminateBackgroundWorker(BackgroundWorkerHandle *handle);
|
||||||
|
@ -219,7 +219,7 @@ setup_background_workers(int nworkers, dsm_segment *seg)
|
|||||||
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
sprintf(worker.bgw_library_name, "test_shm_mq");
|
sprintf(worker.bgw_library_name, "test_shm_mq");
|
||||||
sprintf(worker.bgw_function_name, "test_shm_mq_main");
|
sprintf(worker.bgw_function_name, "test_shm_mq_main");
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN, "test_shm_mq");
|
snprintf(worker.bgw_type, BGW_MAXLEN, "test_shm_mq");
|
||||||
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(seg));
|
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(seg));
|
||||||
/* set bgw_notify_pid, so we can detect if the worker stops */
|
/* set bgw_notify_pid, so we can detect if the worker stops */
|
||||||
worker.bgw_notify_pid = MyProcPid;
|
worker.bgw_notify_pid = MyProcPid;
|
||||||
|
@ -111,7 +111,7 @@ initialize_worker_spi(worktable *table)
|
|||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
SPI_connect();
|
SPI_connect();
|
||||||
PushActiveSnapshot(GetTransactionSnapshot());
|
PushActiveSnapshot(GetTransactionSnapshot());
|
||||||
pgstat_report_activity(STATE_RUNNING, "initializing spi_worker schema");
|
pgstat_report_activity(STATE_RUNNING, "initializing worker_spi schema");
|
||||||
|
|
||||||
/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
|
/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
|
||||||
initStringInfo(&buf);
|
initStringInfo(&buf);
|
||||||
@ -359,7 +359,8 @@ _PG_init(void)
|
|||||||
*/
|
*/
|
||||||
for (i = 1; i <= worker_spi_total_workers; i++)
|
for (i = 1; i <= worker_spi_total_workers; i++)
|
||||||
{
|
{
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
|
snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
|
||||||
|
snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
|
||||||
worker.bgw_main_arg = Int32GetDatum(i);
|
worker.bgw_main_arg = Int32GetDatum(i);
|
||||||
|
|
||||||
RegisterBackgroundWorker(&worker);
|
RegisterBackgroundWorker(&worker);
|
||||||
@ -385,7 +386,8 @@ worker_spi_launch(PG_FUNCTION_ARGS)
|
|||||||
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
sprintf(worker.bgw_library_name, "worker_spi");
|
sprintf(worker.bgw_library_name, "worker_spi");
|
||||||
sprintf(worker.bgw_function_name, "worker_spi_main");
|
sprintf(worker.bgw_function_name, "worker_spi_main");
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
|
snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
|
||||||
|
snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
|
||||||
worker.bgw_main_arg = Int32GetDatum(i);
|
worker.bgw_main_arg = Int32GetDatum(i);
|
||||||
/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
|
/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
|
||||||
worker.bgw_notify_pid = MyProcPid;
|
worker.bgw_notify_pid = MyProcPid;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user