On 5/30/17 23:10, Peter Eisentraut wrote:
> Here is a proposed solution that splits bgw_name into bgw_type and
> bgw_name_extra.  bgw_type shows up in pg_stat_activity.backend_type.
> Uses of application_name are removed, because they are no longer
> necessary to identity the process type.

Updated patch incorporating the feedback.  I have kept bgw_name as it
was and just added bgw_type completely independently.

One open question is how to treat a missing (empty) bgw_type.  I
currently fill in bgw_name as a fallback.  We could also treat it as an
error or a warning as a transition measure.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 73142adf6e56e44d97bd9f855072cba17ef5ea4c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Thu, 31 Aug 2017 12:24:47 -0400
Subject: [PATCH v2] 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 and some log messages no longer call
out that a process is a "background worker" but just show the bgw_type.
That way, being a background worker is effectively an implementation
detail now that is not shown to the user.
---
 contrib/pg_prewarm/autoprewarm.c           |  6 ++--
 doc/src/sgml/bgworker.sgml                 | 12 +++++--
 src/backend/access/transam/parallel.c      |  1 +
 src/backend/postmaster/bgworker.c          | 53 +++++++++++++++++++++++++++---
 src/backend/postmaster/postmaster.c        | 10 ++----
 src/backend/replication/logical/launcher.c |  3 ++
 src/backend/utils/adt/pgstatfuncs.c        | 16 +++++++--
 src/include/postmaster/bgworker.h          |  2 ++
 src/test/modules/test_shm_mq/setup.c       |  2 +-
 src/test/modules/worker_spi/worker_spi.c   |  8 +++--
 10 files changed, 91 insertions(+), 22 deletions(-)

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index cc0350e6d6..006c3153db 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -800,7 +800,8 @@ apw_start_master_worker(void)
        worker.bgw_start_time = BgWorkerStart_ConsistentState;
        strcpy(worker.bgw_library_name, "pg_prewarm");
        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)
        {
@@ -840,7 +841,8 @@ apw_start_database_worker(void)
        worker.bgw_start_time = BgWorkerStart_ConsistentState;
        strcpy(worker.bgw_library_name, "pg_prewarm");
        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 */
        worker.bgw_notify_pid = MyProcPid;
diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index b422323081..822632bf02 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -51,6 +51,7 @@ <title>Background Worker Processes</title>
 typedef struct BackgroundWorker
 {
     char        bgw_name[BGW_MAXLEN];
+    char        bgw_type[BGW_MAXLEN];
     int         bgw_flags;
     BgWorkerStartTime bgw_start_time;
     int         bgw_restart_time;       /* in seconds, or BGW_NEVER_RESTART */
@@ -64,8 +65,15 @@ <title>Background Worker Processes</title>
   </para>
 
   <para>
-   <structfield>bgw_name</> is a string to be used in log messages, process
-   listings and similar contexts.
+   <structfield>bgw_name</> and <structfield>bgw_type</structfield> are
+   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 string for <structfield>bgw_type</structfield> somehow, but that is not
+   strictly required.)
   </para>
 
   <para>
diff --git a/src/backend/access/transam/parallel.c 
b/src/backend/access/transam/parallel.c
index 17b10383e4..9828259e6d 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -438,6 +438,7 @@ LaunchParallelWorkers(ParallelContext *pcxt)
        memset(&worker, 0, sizeof(worker));
        snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
                         MyProcPid);
+       snprintf(worker.bgw_type, BGW_MAXLEN, "parallel worker");
        worker.bgw_flags =
                BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
                | BGWORKER_CLASS_PARALLEL;
diff --git a/src/backend/postmaster/bgworker.c 
b/src/backend/postmaster/bgworker.c
index 28af6f0f07..da7d12d91a 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -344,6 +344,8 @@ BackgroundWorkerStateChange(void)
                 */
                ascii_safe_strlcpy(rw->rw_worker.bgw_name,
                                                   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,
                                                   
slot->worker.bgw_library_name, BGW_MAXLEN);
                ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
@@ -630,6 +632,12 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int 
elevel)
                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;
 }
 
@@ -670,8 +678,8 @@ bgworker_die(SIGNAL_ARGS)
 
        ereport(FATAL,
                        (errcode(ERRCODE_ADMIN_SHUTDOWN),
-                        errmsg("terminating background worker \"%s\" due to 
administrator command",
-                                       MyBgworkerEntry->bgw_name)));
+                        errmsg("terminating %s due to administrator command",
+                                       MyBgworkerEntry->bgw_type)));
 }
 
 /*
@@ -700,7 +708,6 @@ void
 StartBackgroundWorker(void)
 {
        sigjmp_buf      local_sigjmp_buf;
-       char            buf[MAXPGPATH];
        BackgroundWorker *worker = MyBgworkerEntry;
        bgworker_main_type entrypt;
 
@@ -710,8 +717,7 @@ StartBackgroundWorker(void)
        IsBackgroundWorker = true;
 
        /* Identify myself via ps */
-       snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
-       init_ps_display(buf, "", "", "");
+       init_ps_display(worker->bgw_name, "", "", "");
 
        /*
         * 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)
                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;
+}
diff --git a/src/backend/postmaster/postmaster.c 
b/src/backend/postmaster/postmaster.c
index 95180b2ef5..cf4bffa8b3 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3096,7 +3096,6 @@ static bool
 CleanupBackgroundWorker(int pid,
                                                int exitstatus) /* child's exit 
status */
 {
-       char            namebuf[MAXPGPATH];
        slist_mutable_iter iter;
 
        slist_foreach_modify(iter, &BackgroundWorkerList)
@@ -3114,9 +3113,6 @@ CleanupBackgroundWorker(int pid,
                        exitstatus = 0;
 #endif
 
-               snprintf(namebuf, MAXPGPATH, "%s: %s", _("worker process"),
-                                rw->rw_worker.bgw_name);
-
                if (!EXIT_STATUS_0(exitstatus))
                {
                        /* Record timestamp, so we know when to restart the 
worker. */
@@ -3138,7 +3134,7 @@ CleanupBackgroundWorker(int pid,
                {
                        if (!EXIT_STATUS_0(exitstatus) && 
!EXIT_STATUS_1(exitstatus))
                        {
-                               HandleChildCrash(pid, exitstatus, namebuf);
+                               HandleChildCrash(pid, exitstatus, 
rw->rw_worker.bgw_name);
                                return true;
                        }
                }
@@ -3151,7 +3147,7 @@ CleanupBackgroundWorker(int pid,
                if (!ReleasePostmasterChildSlot(rw->rw_child_slot) &&
                        (rw->rw_worker.bgw_flags & BGWORKER_SHMEM_ACCESS) != 0)
                {
-                       HandleChildCrash(pid, exitstatus, namebuf);
+                       HandleChildCrash(pid, exitstatus, 
rw->rw_worker.bgw_name);
                        return true;
                }
 
@@ -3176,7 +3172,7 @@ CleanupBackgroundWorker(int pid,
                ReportBackgroundWorkerExit(&iter);      /* report child death */
 
                LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG,
-                                        namebuf, pid, exitstatus);
+                                        rw->rw_worker.bgw_name, pid, 
exitstatus);
 
                return true;
        }
diff --git a/src/backend/replication/logical/launcher.c 
b/src/backend/replication/logical/launcher.c
index 6c894421a3..cf5f02aef8 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -421,6 +421,7 @@ logicalrep_worker_launch(Oid dbid, Oid subid, const char 
*subname, Oid userid,
        else
                snprintf(bgw.bgw_name, BGW_MAXLEN,
                                 "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_notify_pid = MyProcPid;
@@ -768,6 +769,8 @@ ApplyLauncherRegister(void)
        snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
        snprintf(bgw.bgw_name, BGW_MAXLEN,
                         "logical replication launcher");
+       snprintf(bgw.bgw_type, BGW_MAXLEN,
+                        "logical replication launcher");
        bgw.bgw_restart_time = 5;
        bgw.bgw_notify_pid = 0;
        bgw.bgw_main_arg = (Datum) 0;
diff --git a/src/backend/utils/adt/pgstatfuncs.c 
b/src/backend/utils/adt/pgstatfuncs.c
index 20ce48b2d8..dd5898ec0a 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -21,6 +21,7 @@
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "postmaster/bgworker_internals.h"
 #include "postmaster/postmaster.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
@@ -820,8 +821,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                                }
                        }
                        /* Add backend type */
-                       values[17] =
-                               
CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
+                       if (beentry->st_backendType == B_BG_WORKER)
+                       {
+                               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
                {
diff --git a/src/include/postmaster/bgworker.h 
b/src/include/postmaster/bgworker.h
index e2ecd3c9eb..6b4e631880 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -88,6 +88,7 @@ typedef enum
 typedef struct BackgroundWorker
 {
        char            bgw_name[BGW_MAXLEN];
+       char            bgw_type[BGW_MAXLEN];
        int                     bgw_flags;
        BgWorkerStartTime bgw_start_time;
        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
                        WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle 
*);
+extern const char *GetBackgroundWorkerTypeByPid(pid_t pid);
 
 /* Terminate a bgworker */
 extern void TerminateBackgroundWorker(BackgroundWorkerHandle *handle);
diff --git a/src/test/modules/test_shm_mq/setup.c 
b/src/test/modules/test_shm_mq/setup.c
index 3ae9018360..561f6f9bac 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -219,7 +219,7 @@ setup_background_workers(int nworkers, dsm_segment *seg)
        worker.bgw_restart_time = BGW_NEVER_RESTART;
        sprintf(worker.bgw_library_name, "test_shm_mq");
        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));
        /* set bgw_notify_pid, so we can detect if the worker stops */
        worker.bgw_notify_pid = MyProcPid;
diff --git a/src/test/modules/worker_spi/worker_spi.c 
b/src/test/modules/worker_spi/worker_spi.c
index 12c8cd5774..4c6ab6d575 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -111,7 +111,7 @@ initialize_worker_spi(worktable *table)
        StartTransactionCommand();
        SPI_connect();
        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? */
        initStringInfo(&buf);
@@ -359,7 +359,8 @@ _PG_init(void)
         */
        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);
 
                RegisterBackgroundWorker(&worker);
@@ -385,7 +386,8 @@ worker_spi_launch(PG_FUNCTION_ARGS)
        worker.bgw_restart_time = BGW_NEVER_RESTART;
        sprintf(worker.bgw_library_name, "worker_spi");
        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);
        /* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup 
*/
        worker.bgw_notify_pid = MyProcPid;

base-commit: b5c75feca7ffb2667c42b86286e262d6cb709b76
-- 
2.14.1

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to