[PATCH 05/16] Preliminary: Introduce Bgworker process
От | Andres Freund |
---|---|
Тема | [PATCH 05/16] Preliminary: Introduce Bgworker process |
Дата | |
Msg-id | 1339586927-13156-5-git-send-email-andres@2ndquadrant.com обсуждение исходный текст |
Ответ на | [RFC][PATCH] Logical Replication/BDR prototype and architecture (Andres Freund <andres@2ndquadrant.com>) |
Список | pgsql-hackers |
From: Simon Riggs <simon@2ndquadrant.com> Early prototype that allows for just 1 bgworker which calls a function called do_applyprocess(). Expect major changes in this, but not in ways that would effect the apply process. ---src/backend/postmaster/Makefile | 4 +-src/backend/postmaster/bgworker.c | 403 +++++++++++++++++++++++++src/backend/postmaster/postmaster.c | 91 ++++--src/backend/tcop/postgres.c | 5 +src/backend/utils/init/miscinit.c | 5 +-src/backend/utils/init/postinit.c | 3 +-src/backend/utils/misc/guc.c | 37 ++-src/backend/utils/misc/postgresql.conf.sample | 4 +src/include/postmaster/bgworker.h | 29 ++9 files changed, 550 insertions(+), 31 deletions(-)create mode 100644src/backend/postmaster/bgworker.ccreate mode 100644 src/include/postmaster/bgworker.h diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index 3056b09..7b23353 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -12,7 +12,7 @@ subdir = src/backend/postmastertop_builddir = ../../..include $(top_builddir)/src/Makefile.global -OBJS = autovacuum.o bgwriter.o fork_process.o pgarch.o pgstat.o postmaster.o \ - startup.o syslogger.o walwriter.o checkpointer.o +OBJS = autovacuum.o bgworker.o bgwriter.o fork_process.o pgarch.o pgstat.o \ + postmaster.o startup.o syslogger.o walwriter.o checkpointer.oinclude $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c new file mode 100644 index 0000000..8144050 --- /dev/null +++ b/src/backend/postmaster/bgworker.c @@ -0,0 +1,403 @@ +/*------------------------------------------------------------------------- + * + * bgworker.c + * + * PostgreSQL Integrated Worker Daemon + * + * Background workers can execute arbitrary user code. A shared library + * can request creation of a worker using RequestAddinBGWorkerProcess(). + * + * The worker process is forked from the postmaster and then attaches + * to shared memory similarly to an autovacuum worker and finally begins + * executing the supplied WorkerMain function. + * + * If the fork() call fails in the postmaster, it will try again later. + * Note that the failure can only be transient (fork failure due to + * high load, memory pressure, too many processes, etc); more permanent + * problems, like failure to connect to a database, are detected later in the + * worker and dealt with just by having the worker exit normally. Postmaster + * will launch a new worker again later. + * + * Note that there can be more than one worker in a database concurrently. + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/postmaster/bgworker.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include <signal.h> +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> + +#include "access/heapam.h" +#include "access/reloptions.h" +#include "access/transam.h" +#include "access/xact.h" +#include "catalog/dependency.h" +#include "catalog/namespace.h" +#include "catalog/pg_database.h" +#include "commands/dbcommands.h" +#include "commands/vacuum.h" +#include "libpq/pqsignal.h" +#include "miscadmin.h" +#include "pgstat.h" +#include "postmaster/bgworker.h" +#include "postmaster/fork_process.h" +#include "postmaster/postmaster.h" +#include "storage/bufmgr.h" +#include "storage/ipc.h" +#include "storage/latch.h" +#include "storage/pmsignal.h" +#include "storage/proc.h" +#include "storage/procsignal.h" +#include "storage/sinvaladt.h" +#include "tcop/tcopprot.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/memutils.h" +#include "utils/ps_status.h" +#include "utils/rel.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/tqual.h" + + +/* + * GUC parameters + */ +int MaxWorkers; + +static int bgworker_addin_request = 0; +static bool bgworker_addin_request_allowed = true; + +/* Flags to tell if we are in a worker process */ +static bool am_bgworker = false; + +/* Flags set by signal handlers */ +static volatile sig_atomic_t got_SIGHUP = false; +static volatile sig_atomic_t got_SIGUSR2 = false; +static volatile sig_atomic_t got_SIGTERM = false; + +static void bgworker_sigterm_handler(SIGNAL_ARGS); + +NON_EXEC_STATIC void BgWorkerMain(int argc, char *argv[]); + +static bool do_logicalapply(void); + +/******************************************************************** + * BGWORKER CODE + ********************************************************************/ + +/* SIGTERM: time to die */ +static void +bgworker_sigterm_handler(SIGNAL_ARGS) +{ + int save_errno = errno; + + got_SIGTERM = true; + if (MyProc) + SetLatch(&MyProc->procLatch); + + errno = save_errno; +} + +/* + * Main entry point for background worker process, to be called from the + * postmaster. + * + * This code is heavily based on autovacuum.c, q.v. + */ +int +StartBgWorker(void) +{ + pid_t worker_pid; + +#ifdef EXEC_BACKEND + switch ((worker_pid = bgworker_forkexec())) +#else + switch ((worker_pid = fork_process())) +#endif + { + case -1: + ereport(LOG, + (errmsg("could not fork worker process: %m"))); + return 0; + +#ifndef EXEC_BACKEND + case 0: + /* in postmaster child ... */ + /* Close the postmaster's sockets */ + ClosePostmasterPorts(false); + + /* Lose the postmaster's on-exit routines */ + on_exit_reset(); + + BgWorkerMain(0, NULL); + break; +#endif + default: + return (int) worker_pid; + } + + /* shouldn't get here */ + return 0; +} + +/* + * BgWorkerMain + */ +NON_EXEC_STATIC void +BgWorkerMain(int argc, char *argv[]) +{ + sigjmp_buf local_sigjmp_buf; + //Oid dbid = 12037; /* kluge to set dbid for "Postgres" */ + bool init = false; + + /* we are a postmaster subprocess now */ + IsUnderPostmaster = true; + am_bgworker = true; + + /* reset MyProcPid */ + MyProcPid = getpid(); + + /* record Start Time for logging */ + MyStartTime = time(NULL); + + /* Identify myself via ps */ + init_ps_display("worker process", "", "", ""); + + SetProcessingMode(InitProcessing); + + /* + * If possible, make this process a group leader, so that the postmaster + * can signal any child processes too. (autovacuum probably never has any + * child processes, but for consistency we make all postmaster child + * processes do this.) + */ +#ifdef HAVE_SETSID + if (setsid() < 0) + elog(FATAL, "setsid() failed: %m"); +#endif + + /* + * Set up signal handlers. We operate on databases much like a regular + * backend, so we use the same signal handling. See equivalent code in + * tcop/postgres.c. + * + * Currently, we don't pay attention to postgresql.conf changes that + * happen during a single daemon iteration, so we can ignore SIGHUP. + */ + pqsignal(SIGHUP, SIG_IGN); + + /* + * SIGINT is used to signal canceling the current action; SIGTERM + * means abort and exit cleanly, and SIGQUIT means abandon ship. + */ + pqsignal(SIGINT, StatementCancelHandler); + pqsignal(SIGTERM, bgworker_sigterm_handler); // was die); + pqsignal(SIGQUIT, quickdie); + pqsignal(SIGALRM, handle_sig_alarm); + + pqsignal(SIGPIPE, SIG_IGN); + pqsignal(SIGUSR1, procsignal_sigusr1_handler); + pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGFPE, FloatExceptionHandler); + pqsignal(SIGCHLD, SIG_DFL); + + /* Early initialization */ + BaseInit(); + + /* + * Create a per-backend PGPROC struct in shared memory, except in the + * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do + * this before we can use LWLocks (and in the EXEC_BACKEND case we already + * had to do some stuff with LWLocks). + */ +#ifndef EXEC_BACKEND + InitProcess(); +#endif + + /* + * If an exception is encountered, processing resumes here. + * + * See notes in postgres.c about the design of this coding. + */ + if (sigsetjmp(local_sigjmp_buf, 1) != 0) + { + /* Prevents interrupts while cleaning up */ + HOLD_INTERRUPTS(); + + /* Report the error to the server log */ + EmitErrorReport(); + + /* + * We can now go away. Note that because we called InitProcess, a + * callback was registered to do ProcKill, which will clean up + * necessary state. + */ + proc_exit(0); + } + + /* We can now handle ereport(ERROR) */ + PG_exception_stack = &local_sigjmp_buf; + + PG_SETMASK(&UnBlockSig); + + /* + * Force zero_damaged_pages OFF in a worker process, even if it is set + * in postgresql.conf. We don't really want such a dangerous option being + * applied non-interactively. + */ + SetConfigOption("zero_damaged_pages", "false", PGC_SUSET, PGC_S_OVERRIDE); + + /* + * Force statement_timeout to zero to avoid a timeout setting from + * preventing regular maintenance from being executed. + */ + SetConfigOption("statement_timeout", "0", PGC_SUSET, PGC_S_OVERRIDE); + + /* + * Force default_transaction_isolation to READ COMMITTED. We don't + * want to pay the overhead of serializable mode, nor add any risk + * of causing deadlocks or delaying other transactions. + */ + SetConfigOption("default_transaction_isolation", "read committed", + PGC_SUSET, PGC_S_OVERRIDE); + + /* + * Force synchronous replication off to allow regular maintenance even if + * we are waiting for standbys to connect. This is important to ensure we + * aren't blocked from performing anti-wraparound tasks. + */ + if (synchronous_commit > SYNCHRONOUS_COMMIT_LOCAL_FLUSH) + SetConfigOption("synchronous_commit", "local", + PGC_SUSET, PGC_S_OVERRIDE); + + for (;;) + { + bool not_idle; + + /* the normal shutdown case */ + if (got_SIGTERM) + break; + + if (got_SIGHUP) + { + got_SIGHUP = false; + ProcessConfigFile(PGC_SIGHUP); + } + + if (!init) + { + char dbname[NAMEDATALEN] = "postgres"; + + /* + * Connect to the selected database + * + * Note: if we have selected a just-deleted database (due to using + * stale stats info), we'll fail and exit here. + * + * Note that MyProcPort is not setup correctly, so normal + * authentication will simply fail. This is bypassed by moving + * straight to superuser mode, using same trick as autovacuum. + */ + InitPostgres(dbname, InvalidOid, NULL, NULL); + SetProcessingMode(NormalProcessing); + ereport(LOG, + (errmsg("starting worker process on database \"%s\"", dbname))); + + if (PostAuthDelay) + pg_usleep(PostAuthDelay * 1000000L); + + CurrentResourceOwner = ResourceOwnerCreate(NULL, "worker process"); + + init = true; + } + + /* + * If we're initialised correctly we can call the worker code. + */ + if (init) + not_idle = do_logicalapply(); + + if(!not_idle){ + /* Just for test and can be removed. */ + pg_usleep(100000L); + } + } + + /* Normal exit from the bgworker is here */ + ereport(LOG, + (errmsg("worker shutting down"))); + + /* All done, go away */ + proc_exit(0); +} + +bool +IsWorkerProcess(void) +{ + return am_bgworker; +} + +/* + * RequestAddinBgWorkerProcess + * Request a background worker process + * + * This is only useful if called from the _PG_init hook of a library that + * is loaded into the postmaster via shared_preload_libraries. Once + * shared memory has been allocated, calls will be ignored. (We could + * raise an error, but it seems better to make it a no-op, so that + * libraries containing such calls can be reloaded if needed.) + */ +void +RequestAddinBgWorkerProcess(const char *WorkerName, + void *Main, + const char *DBname) +{ + if (IsUnderPostmaster || !bgworker_addin_request_allowed) + return; /* too late */ + bgworker_addin_request++; +} + +/* + * Compute number of BgWorkers to allocate. + */ +int +NumBgWorkers(void) +{ + return 1; + +#ifdef UNUSED + int numWorkers; + + /* + * Include number of workers required by server, for example, + * parallel query worker tasks. + */ + + /* + * Add any requested by loadable modules. + */ + bgworker_addin_request_allowed = false; + numWorkers += bgworker_addin_request; + + return numWorkers; +#endif +} + +static bool +do_logicalapply(void) +{ + elog(LOG, "doing logical apply"); + return false; +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index eeea933..71cfd6d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -103,6 +103,7 @@#include "miscadmin.h"#include "pgstat.h"#include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h"#include "postmaster/fork_process.h"#include "postmaster/pgarch.h"#include "postmaster/postmaster.h" @@ -131,7 +132,7 @@ * children we have and send them appropriate signals when necessary. * * "Special" children such as thestartup, bgwriter and autovacuum launcher - * tasks are not in this list. Autovacuum worker and walsender processes are + * tasks are not in this list. All worker and walsender processes are * in it. Also, "dead_end" children are in it: theseare children launched just * for the purpose of sending a friendly rejection message to a would-be * client. We musttrack them because they are attached to shared memory, @@ -144,6 +145,7 @@ typedef struct bkend long cancel_key; /* cancel key for cancels for this backend */ int child_slot; /* PMChildSlot for this backend, if any */ bool is_autovacuum; /* isit an autovacuum process? */ + bool is_bgworker; /* is it a bgworker process? */ bool dead_end; /* is it going to send anerror and quit? */ Dlelem elem; /* list link in BackendList */} Backend; @@ -216,6 +218,8 @@ static pid_t StartupPID = 0, PgStatPID = 0, SysLoggerPID = 0; +static pid_t *BgWorkerPID; /* Array of PIDs of bg workers */ +/* Startup/shutdown state */#define NoShutdown 0#define SmartShutdown 1 @@ -303,6 +307,8 @@ static volatile sig_atomic_t start_autovac_launcher = false;/* the launcher needs to be signalled tocommunicate some condition */static volatile bool avlauncher_needs_signal = false; +static int NWorkers; +/* * State for assigning random salts and cancel keys. * Also, the global MyCancelKey passes the cancel key assigned toa given @@ -366,12 +372,16 @@ static bool SignalSomeChildren(int signal, int targets);#define BACKEND_TYPE_NORMAL 0x0001 /* normal backend */#define BACKEND_TYPE_AUTOVAC 0x0002 /* autovacuum worker process */#define BACKEND_TYPE_WALSND 0x0004 /* walsender process */ -#define BACKEND_TYPE_ALL 0x0007 /* OR of all the above */ +#define BACKEND_TYPE_BGWORKER 0x0008 /* general bgworker process */ +#define BACKEND_TYPE_ALL 0x000F /* OR of all the above */ + +#define BACKEND_TYPE_WORKER (BACKEND_TYPE_AUTOVAC | BACKEND_TYPE_BGWORKER)static int CountChildren(int target); +static void StartBackgroundWorkers(void);static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);static pid_tStartChildProcess(AuxProcType type); -static void StartAutovacuumWorker(void); +static int StartWorker(bool is_autovacuum);static void InitPostmasterDeathWatchHandle(void);#ifdef EXEC_BACKEND @@ -1037,7 +1047,7 @@ PostmasterMain(int argc, char *argv[]) * handling setup of child processes. See tcop/postgres.c, * bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/walwriter.c, * postmaster/autovacuum.c,postmaster/pgarch.c, postmaster/pgstat.c, - * postmaster/syslogger.c and postmaster/checkpointer.c. + * postmaster/syslogger.c, postmaster/bgworker.c and postmaster/checkpointer.c */ pqinitmask(); PG_SETMASK(&BlockSig); @@ -1085,6 +1095,17 @@ PostmasterMain(int argc, char *argv[]) autovac_init(); /* + * Allocate background workers actually required. + */ + NWorkers = NumBgWorkers(); + if (NWorkers > 0) + { + BgWorkerPID = (pid_t *) MemoryContextAlloc(TopMemoryContext, + NWorkers * sizeof(pid_t)); + memset(BgWorkerPID, 0, NWorkers * sizeof(pid_t)); + } + + /* * Load configuration files for client authentication. */ if (!load_hba()) @@ -1428,6 +1449,10 @@ ServerLoop(void) kill(AutoVacPID, SIGUSR2); } + /* Check all the workers requested are running. */ + if (pmState == PM_RUN) + StartBackgroundWorkers(); + /* * Touch the socket and lock file every 58 minutes, to ensure that * they are not removed by overzealous/tmp-cleaning tasks. We assume @@ -2133,8 +2158,8 @@ pmdie(SIGNAL_ARGS) if (pmState == PM_RUN || pmState == PM_RECOVERY || pmState== PM_HOT_STANDBY || pmState == PM_STARTUP) { - /* autovacuum workers are told to shut down immediately */ - SignalSomeChildren(SIGTERM, BACKEND_TYPE_AUTOVAC); + /* workers are told to shut down immediately */ + SignalSomeChildren(SIGTERM, BACKEND_TYPE_WORKER); /* and the autovac launcher too */ if (AutoVacPID != 0) signal_child(AutoVacPID, SIGTERM); @@ -2203,9 +2228,9 @@ pmdie(SIGNAL_ARGS) { ereport(LOG, (errmsg("abortingany active transactions"))); - /* shut down all backends and autovac workers */ + /* shut down all backends and workers */ SignalSomeChildren(SIGTERM, - BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC); + BACKEND_TYPE_NORMAL | BACKEND_TYPE_WORKER); /* and the autovac launcher too */ if (AutoVacPID != 0) signal_child(AutoVacPID, SIGTERM); @@ -2396,6 +2421,7 @@ reaper(SIGNAL_ARGS) PgArchPID = pgarch_start(); if (PgStatPID == 0) PgStatPID = pgstat_start(); + StartBackgroundWorkers(); /* at this point we are really open for business */ ereport(LOG, @@ -2963,7 +2989,7 @@ PostmasterStateMachine(void) * later after writing the checkpoint record, like the archiver * process. */ - if (CountChildren(BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC) == 0 && + if (CountChildren(BACKEND_TYPE_NORMAL | BACKEND_TYPE_WORKER) == 0 && StartupPID == 0 && WalReceiverPID== 0 && BgWriterPID == 0 && @@ -3202,6 +3228,8 @@ SignalSomeChildren(int signal, int target) if (bp->is_autovacuum) child =BACKEND_TYPE_AUTOVAC; + else if (bp->is_bgworker) + child = BACKEND_TYPE_BGWORKER; else if (IsPostmasterChildWalSender(bp->child_slot)) child = BACKEND_TYPE_WALSND; else @@ -3224,7 +3252,7 @@ SignalSomeChildren(int signal, int target) * * returns: STATUS_ERROR if the fork failed, STATUS_OKotherwise. * - * Note: if you change this code, also consider StartAutovacuumWorker. + * Note: if you change this code, also consider StartWorker. */static intBackendStartup(Port *port) @@ -3325,6 +3353,7 @@ BackendStartup(Port *port) */ bn->pid = pid; bn->is_autovacuum = false; + bn->is_bgworker = false; DLInitElem(&bn->elem, bn); DLAddHead(BackendList, &bn->elem);#ifdef EXEC_BACKEND @@ -4302,7 +4331,7 @@ sigusr1_handler(SIGNAL_ARGS) if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER)) { /* The autovacuum launcher wants us to start a worker process. */ - StartAutovacuumWorker(); + (void) StartWorker(true); } if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER) && @@ -4448,6 +4477,8 @@ CountChildren(int target) if (bp->is_autovacuum) child = BACKEND_TYPE_AUTOVAC; + else if (bp->is_bgworker) + child = BACKEND_TYPE_BGWORKER; else if (IsPostmasterChildWalSender(bp->child_slot)) child = BACKEND_TYPE_WALSND; else @@ -4570,16 +4601,16 @@ StartChildProcess(AuxProcType type)}/* - * StartAutovacuumWorker - * Start an autovac worker process. + * StartWorker + * Start a worker process either for autovacuum or more generally. * * This function is here because it enters theresulting PID into the * postmaster's private backends list. * * NB -- this code very roughly matches BackendStartup.*/ -static void -StartAutovacuumWorker(void) +static int +StartWorker(bool is_autovacuum){ Backend *bn; @@ -4608,22 +4639,26 @@ StartAutovacuumWorker(void) bn->dead_end = false; bn->child_slot = MyPMChildSlot= AssignPostmasterChildSlot(); - bn->pid = StartAutoVacWorker(); + if (is_autovacuum) + bn->pid = StartAutoVacWorker(); + else + bn->pid = StartBgWorker(); + if (bn->pid > 0) { - bn->is_autovacuum = true; + bn->is_autovacuum = is_autovacuum; DLInitElem(&bn->elem, bn); DLAddHead(BackendList,&bn->elem);#ifdef EXEC_BACKEND ShmemBackendArrayAdd(bn);#endif /* allOK */ - return; + return bn->pid; } /* * fork failed, fall through to report -- actual errormessage was - * logged by StartAutoVacWorker + * logged by Start...Worker */ (void) ReleasePostmasterChildSlot(bn->child_slot); free(bn); @@ -4643,11 +4678,25 @@ StartAutovacuumWorker(void) * quick succession between the autovac launcher and postmaster incase * things get ugly. */ - if (AutoVacPID != 0) + if (is_autovacuum && AutoVacPID != 0) { AutoVacWorkerFailed(); avlauncher_needs_signal = true; } + + return 0; +} + +static void +StartBackgroundWorkers(void) +{ + int i; + + for (i = 0; i < NWorkers; i++) + { + if (BgWorkerPID[i] == 0) + BgWorkerPID[i] = StartWorker(false); + }}/* @@ -4687,7 +4736,7 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname) * * This reports the number of entries neededin per-child-process arrays * (the PMChildFlags array, and if EXEC_BACKEND the ShmemBackendArray). - * These arrays include regular backends, autovac workers and walsenders, + * These arrays include regular backends, all workers and walsenders, * but not special children nor dead_end children. This allows the arrays * to have a fixed maximum size, to wit the same too-many-children limit * enforced bycanAcceptConnections(). The exact value isn't too critical diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 51b6df5..5aead05 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -56,6 +56,7 @@#include "parser/analyze.h"#include "parser/parser.h"#include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h"#include "postmaster/postmaster.h"#include "replication/walsender.h"#include "rewrite/rewriteHandler.h" @@ -2841,6 +2842,10 @@ ProcessInterrupts(void) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating autovacuum process due to administrator command"))); + else if (IsWorkerProcess()) + ereport(FATAL, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating worker process due to administrator command"))); else if (RecoveryConflictPending&& RecoveryConflictRetryable) { pgstat_report_recovery_conflict(RecoveryConflictReason); diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index fb376a0..f7ae60a 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -33,6 +33,7 @@#include "mb/pg_wchar.h"#include "miscadmin.h"#include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h"#include "postmaster/postmaster.h"#include "storage/fd.h"#include "storage/ipc.h" @@ -498,9 +499,9 @@ InitializeSessionUserIdStandalone(void){ /* * This function should only be called in single-usermode and in - * autovacuum workers. + * autovacuum or background workers. */ - AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess()); + AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsWorkerProcess()); /* call only once */ AssertState(!OidIsValid(AuthenticatedUserId)); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 1baa67d..3208b5e7 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -36,6 +36,7 @@#include "pgstat.h"#include "postmaster/autovacuum.h"#include "postmaster/postmaster.h" +#include "postmaster/bgworker.h"#include "replication/walsender.h"#include "storage/bufmgr.h"#include "storage/fd.h" @@ -584,7 +585,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, * In standalone mode and inautovacuum worker processes, we use a fixed * ID, otherwise we figure it out from the authenticated user name. */ - if (bootstrap || IsAutoVacuumWorkerProcess()) + if (bootstrap || IsAutoVacuumWorkerProcess() || IsWorkerProcess()) { InitializeSessionUserIdStandalone(); am_superuser = true; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index b756e58..93c798b 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -52,6 +52,7 @@#include "parser/scansup.h"#include "pgstat.h"#include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h"#include "postmaster/bgwriter.h"#include "postmaster/postmaster.h"#include "postmaster/syslogger.h" @@ -107,7 +108,7 @@ * removed, we still could not exceed INT_MAX/4 because some places compute * 4*MaxBackends without anyoverflow check. This is rechecked in * check_maxconnections, since MaxBackends is computed as MaxConnections - * plus autovacuum_max_workers plus one (for the autovacuum launcher). + * plus max_workers plus autovacuum_max_workers plus one (for the autovacuum launcher). */#define MAX_BACKENDS 0x7fffff @@ -197,6 +198,8 @@ static const char *show_tcp_keepalives_interval(void);static const char *show_tcp_keepalives_count(void);staticbool check_maxconnections(int *newval, void **extra, GucSource source);static voidassign_maxconnections(int newval, void *extra); +static bool check_maxworkers(int *newval, void **extra, GucSource source); +static void assign_maxworkers(int newval, void *extra);static bool check_autovacuum_max_workers(int *newval, void **extra,GucSource source);static void assign_autovacuum_max_workers(int newval, void *extra);static bool check_effective_io_concurrency(int*newval, void **extra, GucSource source); @@ -1605,6 +1608,16 @@ static struct config_int ConfigureNamesInt[] = }, { + {"max_workers", PGC_POSTMASTER, CONN_AUTH_SETTINGS, + gettext_noop("Sets the maximum number of background worker processes."), + NULL + }, + &MaxWorkers, + 10, 1, MAX_BACKENDS, + check_maxworkers, assign_maxworkers, NULL + }, + + { {"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS, gettext_noop("Sets the numberof connection slots reserved for superusers."), NULL @@ -8605,7 +8618,7 @@ show_tcp_keepalives_count(void)static boolcheck_maxconnections(int *newval, void **extra, GucSourcesource){ - if (*newval + autovacuum_max_workers + 1 > MAX_BACKENDS) + if (*newval + MaxWorkers + autovacuum_max_workers + 1 > MAX_BACKENDS) return false; return true;} @@ -8613,13 +8626,27 @@ check_maxconnections(int *newval, void **extra, GucSource source)static voidassign_maxconnections(intnewval, void *extra){ - MaxBackends = newval + autovacuum_max_workers + 1; + MaxBackends = newval + MaxWorkers + autovacuum_max_workers + 1; +} + +static bool +check_maxworkers(int *newval, void **extra, GucSource source) +{ + if (*newval + MaxConnections + autovacuum_max_workers + 1 > MAX_BACKENDS) + return false; + return true; +} + +static void +assign_maxworkers(int newval, void *extra) +{ + MaxBackends = newval + MaxConnections + autovacuum_max_workers + 1;}static boolcheck_autovacuum_max_workers(int *newval,void **extra, GucSource source){ - if (MaxConnections + *newval + 1 > MAX_BACKENDS) + if (MaxConnections + MaxWorkers + *newval + 1 > MAX_BACKENDS) return false; return true;} @@ -8627,7 +8654,7 @@ check_autovacuum_max_workers(int *newval, void **extra, GucSource source)static voidassign_autovacuum_max_workers(intnewval, void *extra){ - MaxBackends = MaxConnections + newval + 1; + MaxBackends = MaxConnections + MaxWorkers + newval + 1;}static bool diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index fa75d00..ce3fc08 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -148,6 +148,10 @@#bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round +# - Background Workers - +#max_workers = 10 # max number of general worker subprocesses + # (change requires restart) +# - Asynchronous Behavior -#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h new file mode 100644 index 0000000..92d0a75 --- /dev/null +++ b/src/include/postmaster/bgworker.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * + * bgworker.h + * header file for integrated background worker daemon + * + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/postmaster/bgworker.h + * + *------------------------------------------------------------------------- + */ +#ifndef BGWORKER_H +#define BGWORKER_H + + +/* GUC variables */ +int MaxWorkers; + +extern int StartBgWorker(void); +extern int NumBgWorkers(void); + +extern bool IsWorkerProcess(void); +extern void RequestAddinBgWorkerProcess(const char *WorkerName, + void *Main, + const char *DBname); + +#endif /* BGWORKER_H */ -- 1.7.10.rc3.3.g19a6c.dirty
В списке pgsql-hackers по дате отправления:
Следующее
От: Andres FreundДата:
Сообщение: [PATCH 07/16] Log enough data into the wal to reconstruct logical changes from it if wal_level=logical