]> granicus.if.org Git - postgresql/commitdiff
Add background worker type
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 31 Aug 2017 16:24:47 +0000 (12:24 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 29 Sep 2017 15:08:24 +0000 (11:08 -0400)
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>
contrib/pg_prewarm/autoprewarm.c
doc/src/sgml/bgworker.sgml
src/backend/access/transam/parallel.c
src/backend/postmaster/bgworker.c
src/backend/postmaster/postmaster.c
src/backend/replication/logical/launcher.c
src/backend/utils/adt/pgstatfuncs.c
src/include/postmaster/bgworker.h
src/test/modules/test_shm_mq/setup.c
src/test/modules/worker_spi/worker_spi.c

index cc0350e6d684a21497fabbd085849028ad596019..006c3153db0ece919150c1d9308ff250e0b777fd 100644 (file)
@@ -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;
index b42232308199fd0ba6dc21d5e1c83e1d03b68cfa..ea1b5c0c8e393c2e3abb3c2f7f927f58d12de362 100644 (file)
@@ -51,6 +51,7 @@ typedef void (*bgworker_main_type)(Datum main_arg);
 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,14 @@ typedef struct BackgroundWorker
   </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 type somehow, but that is not strictly required.)
   </para>
 
   <para>
index 13c8ba3b196843bf5c8ec572aa06449e5abdebde..c6f7b7af0e1fd21954f5f835bd8e9de2aa98d4e9 100644 (file)
@@ -467,6 +467,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;
index 28af6f0f07debfa148f114c30b734dffba09bb17..4a3c4b4cc9c025fb672b7ad145681f5b2ce85392 100644 (file)
@@ -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;
 }
 
@@ -671,7 +679,7 @@ bgworker_die(SIGNAL_ARGS)
        ereport(FATAL,
                        (errcode(ERRCODE_ADMIN_SHUTDOWN),
                         errmsg("terminating background worker \"%s\" due to administrator command",
-                                       MyBgworkerEntry->bgw_name)));
+                                       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;
+}
index 1bcbce537a45e59ddd77a845aca5d4a93142b6c9..8a2cc2fc2b488ccb62ef76ae9ac35477332c28e4 100644 (file)
@@ -3117,8 +3117,9 @@ CleanupBackgroundWorker(int pid,
                        exitstatus = 0;
 #endif
 
-               snprintf(namebuf, MAXPGPATH, "%s: %s", _("worker process"),
-                                rw->rw_worker.bgw_name);
+               snprintf(namebuf, MAXPGPATH, _("background worker \"%s\""),
+                                rw->rw_worker.bgw_type);
+
 
                if (!EXIT_STATUS_0(exitstatus))
                {
index 44bdcab3b9796fb21d0c3957cb47d6202e166792..a613ef4757bec209460cf0a1c038190e4cea17ac 100644 (file)
@@ -422,6 +422,7 @@ retry:
        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;
@@ -775,6 +776,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;
index 5a968e3758f6d28a9c85d2cac697931ac9e6d8ca..8d9e7c10ae758bc4b9e67692da315eaa567b0062 100644 (file)
@@ -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"
@@ -823,8 +824,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
                {
index e2ecd3c9eb256d35e3e34b221c117c6adc5073be..6b4e631880d1556c4478fdf5de81c133a5d6d50b 100644 (file)
@@ -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);
index 3ae901836053f60b2c8e6802a1de4c7deb29f011..561f6f9bac3d05657eb983f9facbedaaa1435353 100644 (file)
@@ -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;
index 12c8cd5774c75a2c5d2eaaa4d4e1418dca1c53a9..4c6ab6d575d07c525b899e3785e8f03e2d9d11e1 100644 (file)
@@ -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;