Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7f7485a

Browse files
committed
Allow background workers to be started dynamically.
There is a new API, RegisterDynamicBackgroundWorker, which allowsan ordinary user backend to register a new background writer duringnormal running. This means that it's no longer necessary for allbackground workers to be registered during processing ofshared_preload_libraries, although the option of registering workersat that time remains available.When a background worker exits and will not be restarted, theslot previously used by that background worker is automaticallyreleased and becomes available for reuse. Slots used by backgroundworkers that are configured for automatic restart can't (yet) bereleased without shutting down the system.This commit adds a new source file, bgworker.c, and moves someof the existing control logic for background workers there.Previously, there was little enough logic that it made sense tokeep everything in postmaster.c, but not any more.This commit also makes the worker_spi contrib module into anextension and adds a new function, worker_spi_launch, which canbe used to demonstrate the new facility.
1 parent233bfe0 commit7f7485a

File tree

13 files changed

+710
-209
lines changed

13 files changed

+710
-209
lines changed

‎contrib/worker_spi/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
MODULES = worker_spi
44

5+
EXTENSION = worker_spi
6+
DATA = worker_spi--1.0.sql
7+
58
ifdefUSE_PGXS
69
PG_CONFIG = pg_config
710
PGXS :=$(shell$(PG_CONFIG) --pgxs)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* contrib/worker_spi/worker_spi--1.0.sql*/
2+
3+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
4+
\echo Use"CREATE EXTENSION worker_spi" to load this file. \quit
5+
6+
CREATEFUNCTIONworker_spi_launch(pg_catalog.int4)
7+
RETURNSpg_catalog.bool STRICT
8+
AS'MODULE_PATHNAME'
9+
LANGUAGE C;

‎contrib/worker_spi/worker_spi.c

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@
4242
#include"tcop/utility.h"
4343

4444
PG_MODULE_MAGIC;
45+
PG_FUNCTION_INFO_V1(worker_spi_launch);
4546

4647
void_PG_init(void);
48+
voidworker_spi_main(Datum);
49+
Datumworker_spi_launch(PG_FUNCTION_ARGS);
4750

4851
/* flags set by signal handlers */
4952
staticvolatilesig_atomic_tgot_sighup= false;
@@ -153,11 +156,22 @@ initialize_worker_spi(worktable *table)
153156
pgstat_report_activity(STATE_IDLE,NULL);
154157
}
155158

156-
staticvoid
157-
worker_spi_main(void*main_arg)
159+
void
160+
worker_spi_main(Datummain_arg)
158161
{
159-
worktable*table= (worktable*)main_arg;
162+
intindex=DatumGetInt32(main_arg);
163+
worktable*table;
160164
StringInfoDatabuf;
165+
charname[20];
166+
167+
table=palloc(sizeof(worktable));
168+
sprintf(name,"schema%d",index);
169+
table->schema=pstrdup(name);
170+
table->name=pstrdup("counted");
171+
172+
/* Establish signal handlers before unblocking signals. */
173+
pqsignal(SIGHUP,worker_spi_sighup);
174+
pqsignal(SIGTERM,worker_spi_sigterm);
161175

162176
/* We're now ready to receive signals */
163177
BackgroundWorkerUnblockSignals();
@@ -279,7 +293,7 @@ worker_spi_main(void *main_arg)
279293
pgstat_report_activity(STATE_IDLE,NULL);
280294
}
281295

282-
proc_exit(0);
296+
proc_exit(1);
283297
}
284298

285299
/*
@@ -292,9 +306,7 @@ void
292306
_PG_init(void)
293307
{
294308
BackgroundWorkerworker;
295-
worktable*table;
296309
unsignedinti;
297-
charname[20];
298310

299311
/* get the configuration */
300312
DefineCustomIntVariable("worker_spi.naptime",
@@ -309,6 +321,10 @@ _PG_init(void)
309321
NULL,
310322
NULL,
311323
NULL);
324+
325+
if (!process_shared_preload_libraries_in_progress)
326+
return;
327+
312328
DefineCustomIntVariable("worker_spi.total_workers",
313329
"Number of workers.",
314330
NULL,
@@ -328,23 +344,41 @@ _PG_init(void)
328344
worker.bgw_start_time=BgWorkerStart_RecoveryFinished;
329345
worker.bgw_restart_time=BGW_NEVER_RESTART;
330346
worker.bgw_main=worker_spi_main;
331-
worker.bgw_sighup=worker_spi_sighup;
332-
worker.bgw_sigterm=worker_spi_sigterm;
347+
worker.bgw_sighup=NULL;
348+
worker.bgw_sigterm=NULL;
333349

334350
/*
335351
* Now fill in worker-specific data, and do the actual registrations.
336352
*/
337353
for (i=1;i <=worker_spi_total_workers;i++)
338354
{
339-
sprintf(name,"worker %d",i);
340-
worker.bgw_name=pstrdup(name);
341-
342-
table=palloc(sizeof(worktable));
343-
sprintf(name,"schema%d",i);
344-
table->schema=pstrdup(name);
345-
table->name=pstrdup("counted");
346-
worker.bgw_main_arg= (void*)table;
355+
snprintf(worker.bgw_name,BGW_MAXLEN,"worker %d",i);
356+
worker.bgw_main_arg=Int32GetDatum(i);
347357

348358
RegisterBackgroundWorker(&worker);
349359
}
350360
}
361+
362+
/*
363+
* Dynamically launch an SPI worker.
364+
*/
365+
Datum
366+
worker_spi_launch(PG_FUNCTION_ARGS)
367+
{
368+
int32i=PG_GETARG_INT32(0);
369+
BackgroundWorkerworker;
370+
371+
worker.bgw_flags=BGWORKER_SHMEM_ACCESS |
372+
BGWORKER_BACKEND_DATABASE_CONNECTION;
373+
worker.bgw_start_time=BgWorkerStart_RecoveryFinished;
374+
worker.bgw_restart_time=BGW_NEVER_RESTART;
375+
worker.bgw_main=NULL;/* new worker might not have library loaded */
376+
sprintf(worker.bgw_library_name,"worker_spi");
377+
sprintf(worker.bgw_function_name,"worker_spi_main");
378+
worker.bgw_sighup=NULL;/* new worker might not have library loaded */
379+
worker.bgw_sigterm=NULL;/* new worker might not have library loaded */
380+
snprintf(worker.bgw_name,BGW_MAXLEN,"worker %d",i);
381+
worker.bgw_main_arg=Int32GetDatum(i);
382+
383+
PG_RETURN_BOOL(RegisterDynamicBackgroundWorker(&worker));
384+
}

‎contrib/worker_spi/worker_spi.control

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# worker_spi extension
2+
comment = 'Sample background worker'
3+
default_version = '1.0'
4+
module_pathname = '$libdir/worker_spi'
5+
relocatable = true

‎doc/src/sgml/bgworker.sgml

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,35 @@
3030
</warning>
3131

3232
<para>
33-
Only modules listed in <varname>shared_preload_libraries</> can run
34-
background workers. A module wishing to run a background worker needs
35-
to register it by calling
33+
Background workers can be initialized at the time that
34+
<productname>PostgreSQL</> is started including the module name in
35+
<varname>shared_preload_libraries</>. A module wishing to run a background
36+
worker can register it by calling
3637
<function>RegisterBackgroundWorker(<type>BackgroundWorker *worker</type>)</function>
37-
from its <function>_PG_init()</>.
38+
from its <function>_PG_init()</>. Background workers can also be started
39+
after the system is up and running by calling the function
40+
<function>RegisterDynamicBackgroundWorker</function>(<type>BackgroundWorker
41+
*worker</type>). Unlike <function>RegisterBackgroundWorker</>, which can
42+
only be called from within the postmaster,
43+
<function>RegisterDynamicBackgroundWorker</function> must be called from
44+
a regular backend.
45+
</para>
46+
47+
<para>
3848
The structure <structname>BackgroundWorker</structname> is defined thus:
3949
<programlisting>
4050
typedef void (*bgworker_main_type)(void *main_arg);
4151
typedef void (*bgworker_sighdlr_type)(SIGNAL_ARGS);
4252
typedef struct BackgroundWorker
4353
{
44-
char*bgw_name;
54+
charbgw_name[BGW_MAXLEN];
4555
int bgw_flags;
4656
BgWorkerStartTime bgw_start_time;
4757
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
48-
bgworker_main_type bgw_main;
49-
void *bgw_main_arg;
58+
bgworker_main_type bgw_main;
59+
char bgw_library_name[BGW_MAXLEN]; /* only if bgw_main is NULL */
60+
char bgw_function_name[BGW_MAXLEN]; /* only if bgw_main is NULL */
61+
Datum bgw_main_arg;
5062
bgworker_sighdlr_type bgw_sighup;
5163
bgworker_sighdlr_type bgw_sigterm;
5264
} BackgroundWorker;
@@ -101,15 +113,40 @@ typedef struct BackgroundWorker
101113
<structfield>bgw_main_arg</structfield> will be passed to it as its only
102114
argument. Note that the global variable <literal>MyBgworkerEntry</literal>
103115
points to a copy of the <structname>BackgroundWorker</structname> structure
104-
passed at registration time.
116+
passed at registration time. <structfield>bgw_main</structfield> may be
117+
NULL; in that case, <structfield>bgw_library_name</structfield> and
118+
<structfield>bgw_function_name</structfield> will be used to determine
119+
the entrypoint. This is useful for background workers launched after
120+
postmaster startup, where the postmaster does not have the requisite
121+
library loaded.
122+
</para>
123+
124+
<para>
125+
<structfield>bgw_library_name</structfield> is the name of a library in
126+
which the initial entrypoint for the background worker should be sought.
127+
It is ignored unless <structfield>bgw_main</structfield> is NULL.
128+
But if <structfield>bgw_main</structfield> is NULL, then the named library
129+
will be dynamically loaded by the worker process and
130+
<structfield>bgw_function_name</structfield> will be used to identify
131+
the function to be called.
132+
</para>
133+
134+
<para>
135+
<structfield>bgw_function_name</structfield> is the name of a function in
136+
a dynamically loaded library which should be used as the initial entrypoint
137+
for a new background worker. It is ignored unless
138+
<structfield>bgw_main</structfield> is NULL.
105139
</para>
106140

107141
<para>
108142
<structfield>bgw_sighup</structfield> and <structfield>bgw_sigterm</> are
109143
pointers to functions that will be installed as signal handlers for the new
110144
process. If <structfield>bgw_sighup</> is NULL, then <literal>SIG_IGN</>
111145
is used; if <structfield>bgw_sigterm</> is NULL, a handler is installed that
112-
will terminate the process after logging a suitable message.
146+
will terminate the process after logging a suitable message. These
147+
fields should not be used if <structfield>bgw_main</> is NULL; instead,
148+
the worker process should set its own signal handlers before calling
149+
<function>BackgroundWorkerUnblockSignals()</function>.
113150
</para>
114151

115152
<para>Once running, the process can connect to a database by calling

‎src/backend/postmaster/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ subdir = src/backend/postmaster
1212
top_builddir = ../../..
1313
include$(top_builddir)/src/Makefile.global
1414

15-
OBJS = autovacuum.obgwriter.ofork_process.opgarch.opgstat.o postmaster.o\
16-
startup.osyslogger.owalwriter.ocheckpointer.o
15+
OBJS = autovacuum.obgworker.obgwriter.ocheckpointer.ofork_process.o\
16+
pgarch.opgstat.opostmaster.ostartup.o syslogger.o walwriter.o
1717

1818
include$(top_srcdir)/src/backend/common.mk

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp