bg worker: patch 4 of 6 - renaming
Started by Markus Wannerover 15 years ago1 messages
Lots of variable renaming and comment adjustment, mostly to achieve a
consistent naming. The former launcher gets renamed to coordinator and
the avworkers to background (bg)workers. No functional change (hopefully).
The GUC autovacuum_max_workers got renamed to max_background_workers.
Attachments:
step4-renamed.difftext/x-diff; charset=iso-8859-1; name=step4-renamed.diffDownload
*** src/backend/access/transam/varsup.c 058cb2f268e956e37724f1d05d98946d1cc56ab4
--- src/backend/access/transam/varsup.c 5e3252795acfc8e04994336e4b432bdd0bc13238
*************** GetNewTransactionId(bool isSubXact)
*** 102,108 ****
if (IsUnderPostmaster && (xid % 65536) == 0)
{
msg = IMessageCreate(IMSGT_FORCE_VACUUM, 0);
! IMessageActivate(msg, GetAutovacuumLauncherId());
}
if (IsUnderPostmaster &&
--- 102,108 ----
if (IsUnderPostmaster && (xid % 65536) == 0)
{
msg = IMessageCreate(IMSGT_FORCE_VACUUM, 0);
! IMessageActivate(msg, GetCoordinatorId());
}
if (IsUnderPostmaster &&
*************** SetTransactionIdLimit(TransactionId olde
*** 348,354 ****
IsUnderPostmaster && !InRecovery)
{
msg = IMessageCreate(IMSGT_FORCE_VACUUM, 0);
! IMessageActivate(msg, GetAutovacuumLauncherId());
}
/* Give an immediate warning if past the wrap warn point */
--- 348,354 ----
IsUnderPostmaster && !InRecovery)
{
msg = IMessageCreate(IMSGT_FORCE_VACUUM, 0);
! IMessageActivate(msg, GetCoordinatorId());
}
/* Give an immediate warning if past the wrap warn point */
============================================================
*** src/backend/commands/vacuum.c 50cc1c597a82a6eb85c4ffdf83e07a0ede873646
--- src/backend/commands/vacuum.c 5cad7d65313d1dd67a70016906a2ee6d88043022
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 126,132 ****
* Send info about dead objects to the statistics collector, unless we are
* in autovacuum --- autovacuum.c does this for itself.
*/
! if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
pgstat_vacuum_stat();
/*
--- 126,132 ----
* Send info about dead objects to the statistics collector, unless we are
* in autovacuum --- autovacuum.c does this for itself.
*/
! if ((vacstmt->options & VACOPT_VACUUM) && !IsBackgroundWorkerProcess())
pgstat_vacuum_stat();
/*
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 182,188 ****
else
{
Assert(vacstmt->options & VACOPT_ANALYZE);
! if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
use_own_xacts = false;
--- 182,188 ----
else
{
Assert(vacstmt->options & VACOPT_ANALYZE);
! if (IsBackgroundWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
use_own_xacts = false;
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 278,284 ****
StartTransactionCommand();
}
! if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
--- 278,284 ----
StartTransactionCommand();
}
! if ((vacstmt->options & VACOPT_VACUUM) && !IsBackgroundWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
============================================================
*** src/backend/postmaster/postmaster.c e6a455be46eee967cafa76cef125cedef4ba986f
--- src/backend/postmaster/postmaster.c 7c8ba1424aa374a2583c65fd912f563e94ab0a73
***************
*** 131,137 ****
* authorization phase). This is used mainly to keep track of how many
* children we have and send them appropriate signals when necessary.
*
! * "Special" children such as the startup, bgwriter and autovacuum launcher
* tasks are not in this list. Autovacuum worker and walsender processes are
* in it. Also, "dead_end" children are in it: these are children launched just
* for the purpose of sending a friendly rejection message to a would-be
--- 131,137 ----
* authorization phase). This is used mainly to keep track of how many
* children we have and send them appropriate signals when necessary.
*
! * "Special" children such as the startup, bgwriter and the coordinator
* tasks are not in this list. Autovacuum worker and walsender processes are
* in it. Also, "dead_end" children are in it: these are children launched just
* for the purpose of sending a friendly rejection message to a would-be
*************** typedef struct bkend
*** 144,150 ****
pid_t pid; /* process id of backend */
long cancel_key; /* cancel key for cancels for this backend */
int child_slot; /* PMChildSlot for this backend, if any */
! bool is_autovacuum; /* is it an autovacuum process? */
bool dead_end; /* is it going to send an error and quit? */
Dlelem elem; /* list link in BackendList */
} Backend;
--- 144,150 ----
pid_t pid; /* process id of backend */
long cancel_key; /* cancel key for cancels for this backend */
int child_slot; /* PMChildSlot for this backend, if any */
! bool is_bgworker; /* is it a background worker? */
bool dead_end; /* is it going to send an error and quit? */
Dlelem elem; /* list link in BackendList */
} Backend;
*************** static pid_t StartupPID = 0,
*** 209,215 ****
BgWriterPID = 0,
WalWriterPID = 0,
WalReceiverPID = 0,
! AutoVacPID = 0,
PgArchPID = 0,
PgStatPID = 0,
SysLoggerPID = 0;
--- 209,215 ----
BgWriterPID = 0,
WalWriterPID = 0,
WalReceiverPID = 0,
! CoordinatorPID = 0,
PgArchPID = 0,
PgStatPID = 0,
SysLoggerPID = 0;
*************** bool redirection_done = false; /* stder
*** 296,302 ****
/* the launcher needs to be signalled to communicate some condition */
! static volatile bool avlauncher_needs_signal = false;
/*
* State for assigning random salts and cancel keys.
--- 296,302 ----
/* the launcher needs to be signalled to communicate some condition */
! static volatile bool coordinator_needs_signal = false;
/*
* State for assigning random salts and cancel keys.
*************** static bool SignalSomeChildren(int signa
*** 354,360 ****
static bool SignalSomeChildren(int signal, int targets);
#define SignalChildren(sig) SignalSomeChildren(sig, BACKEND_TYPE_ALL)
! #define SignalAutovacWorkers(sig) SignalSomeChildren(sig, BACKEND_TYPE_AUTOVAC)
/*
* Possible types of a backend. These are OR-able request flag bits
--- 354,360 ----
static bool SignalSomeChildren(int signal, int targets);
#define SignalChildren(sig) SignalSomeChildren(sig, BACKEND_TYPE_ALL)
! #define SignalBackgroundWorkers(sig) SignalSomeChildren(sig, BACKEND_TYPE_AUTOVAC)
/*
* Possible types of a backend. These are OR-able request flag bits
*************** static pid_t StartChildProcess(AuxProcTy
*** 368,374 ****
static int CountChildren(int target);
static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
static pid_t StartChildProcess(AuxProcType type);
! static void StartAutovacuumWorker(void);
#ifdef EXEC_BACKEND
--- 368,374 ----
static int CountChildren(int target);
static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
static pid_t StartChildProcess(AuxProcType type);
! static void StartBgWorker(void);
#ifdef EXEC_BACKEND
*************** ServerLoop(void)
*** 1460,1468 ****
if (WalWriterPID == 0 && pmState == PM_RUN)
WalWriterPID = StartWalWriter();
! /* If we have lost the autovacuum launcher, try to start a new one */
! if (AutoVacPID == 0 && pmState == PM_RUN)
! AutoVacPID = StartAutoVacLauncher();
/* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 && pmState == PM_RUN)
--- 1460,1468 ----
if (WalWriterPID == 0 && pmState == PM_RUN)
WalWriterPID = StartWalWriter();
! /* If we have lost the coordinator, try to start a new one */
! if (CoordinatorPID == 0 && pmState == PM_RUN)
! CoordinatorPID = StartCoordinator();
/* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 && pmState == PM_RUN)
*************** ServerLoop(void)
*** 1472,1483 ****
if (PgStatPID == 0 && pmState == PM_RUN)
PgStatPID = pgstat_start();
! /* If we need to signal the autovacuum launcher, do so now */
! if (avlauncher_needs_signal)
{
! avlauncher_needs_signal = false;
! if (AutoVacPID != 0)
! kill(AutoVacPID, SIGUSR2);
}
/*
--- 1472,1483 ----
if (PgStatPID == 0 && pmState == PM_RUN)
PgStatPID = pgstat_start();
! /* if we need to signal the coordinator, do so now */
! if (coordinator_needs_signal)
{
! coordinator_needs_signal = false;
! if (CoordinatorPID != 0)
! kill(CoordinatorPID, SIGUSR2);
}
/*
*************** SIGHUP_handler(SIGNAL_ARGS)
*** 2104,2111 ****
signal_child(WalWriterPID, SIGHUP);
if (WalReceiverPID != 0)
signal_child(WalReceiverPID, SIGHUP);
! if (AutoVacPID != 0)
! signal_child(AutoVacPID, SIGHUP);
if (PgArchPID != 0)
signal_child(PgArchPID, SIGHUP);
if (SysLoggerPID != 0)
--- 2104,2111 ----
signal_child(WalWriterPID, SIGHUP);
if (WalReceiverPID != 0)
signal_child(WalReceiverPID, SIGHUP);
! if (CoordinatorPID != 0)
! signal_child(CoordinatorPID, SIGHUP);
if (PgArchPID != 0)
signal_child(PgArchPID, SIGHUP);
if (SysLoggerPID != 0)
*************** pmdie(SIGNAL_ARGS)
*** 2164,2174 ****
if (pmState == PM_RUN || pmState == PM_RECOVERY ||
pmState == PM_HOT_STANDBY || pmState == PM_STARTUP)
{
! /* autovacuum workers are told to shut down immediately */
! SignalAutovacWorkers(SIGTERM);
! /* and the autovac launcher too */
! if (AutoVacPID != 0)
! signal_child(AutoVacPID, SIGTERM);
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
--- 2164,2174 ----
if (pmState == PM_RUN || pmState == PM_RECOVERY ||
pmState == PM_HOT_STANDBY || pmState == PM_STARTUP)
{
! /* background workers are told to shut down immediately */
! SignalBackgroundWorkers(SIGTERM);
! /* and the coordinator too */
! if (CoordinatorPID != 0)
! signal_child(CoordinatorPID, SIGTERM);
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
*************** pmdie(SIGNAL_ARGS)
*** 2225,2236 ****
{
ereport(LOG,
(errmsg("aborting any active transactions")));
! /* shut down all backends and autovac workers */
SignalSomeChildren(SIGTERM,
BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC);
! /* and the autovac launcher too */
! if (AutoVacPID != 0)
! signal_child(AutoVacPID, SIGTERM);
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
--- 2225,2236 ----
{
ereport(LOG,
(errmsg("aborting any active transactions")));
! /* shut down all backends and background workers */
SignalSomeChildren(SIGTERM,
BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC);
! /* and the coordinator too */
! if (CoordinatorPID != 0)
! signal_child(CoordinatorPID, SIGTERM);
/* and the walwriter too */
if (WalWriterPID != 0)
signal_child(WalWriterPID, SIGTERM);
*************** pmdie(SIGNAL_ARGS)
*** 2263,2270 ****
signal_child(WalWriterPID, SIGQUIT);
if (WalReceiverPID != 0)
signal_child(WalReceiverPID, SIGQUIT);
! if (AutoVacPID != 0)
! signal_child(AutoVacPID, SIGQUIT);
if (PgArchPID != 0)
signal_child(PgArchPID, SIGQUIT);
if (PgStatPID != 0)
--- 2263,2270 ----
signal_child(WalWriterPID, SIGQUIT);
if (WalReceiverPID != 0)
signal_child(WalReceiverPID, SIGQUIT);
! if (CoordinatorPID != 0)
! signal_child(CoordinatorPID, SIGQUIT);
if (PgArchPID != 0)
signal_child(PgArchPID, SIGQUIT);
if (PgStatPID != 0)
*************** reaper(SIGNAL_ARGS)
*** 2382,2389 ****
*/
if (WalWriterPID == 0)
WalWriterPID = StartWalWriter();
! if (AutoVacPID == 0)
! AutoVacPID = StartAutoVacLauncher();
if (XLogArchivingActive() && PgArchPID == 0)
PgArchPID = pgarch_start();
if (PgStatPID == 0)
--- 2382,2389 ----
*/
if (WalWriterPID == 0)
WalWriterPID = StartWalWriter();
! if (CoordinatorPID == 0)
! CoordinatorPID = StartCoordinator();
if (XLogArchivingActive() && PgArchPID == 0)
PgArchPID = pgarch_start();
if (PgStatPID == 0)
*************** reaper(SIGNAL_ARGS)
*** 2481,2497 ****
}
/*
! * Was it the autovacuum launcher? Normal exit can be ignored; we'll
! * start a new one at the next iteration of the postmaster's main
* loop, if necessary. Any other exit condition is treated as a
* crash.
*/
! if (pid == AutoVacPID)
{
! AutoVacPID = 0;
if (!EXIT_STATUS_0(exitstatus))
HandleChildCrash(pid, exitstatus,
! _("autovacuum launcher process"));
continue;
}
--- 2481,2497 ----
}
/*
! * Was it the coordinator? Normal exit can be ignored; we'll start
! * a new coordinator at the next iteration of the postmaster's main
* loop, if necessary. Any other exit condition is treated as a
* crash.
*/
! if (pid == CoordinatorPID)
{
! CoordinatorPID = 0;
if (!EXIT_STATUS_0(exitstatus))
HandleChildCrash(pid, exitstatus,
! _("coordinator process"));
continue;
}
*************** CleanupBackend(int pid,
*** 2615,2621 ****
/*
* HandleChildCrash -- cleanup after failed backend, bgwriter, walwriter,
! * or autovacuum.
*
* The objectives here are to clean up our local state about the child
* process, and to signal all other remaining children to quickdie.
--- 2615,2621 ----
/*
* HandleChildCrash -- cleanup after failed backend, bgwriter, walwriter,
! * or coordinator.
*
* The objectives here are to clean up our local state about the child
* process, and to signal all other remaining children to quickdie.
*************** HandleChildCrash(int pid, int exitstatus
*** 2732,2747 ****
signal_child(WalReceiverPID, (SendStop ? SIGSTOP : SIGQUIT));
}
! /* Take care of the autovacuum launcher too */
! if (pid == AutoVacPID)
! AutoVacPID = 0;
! else if (AutoVacPID != 0 && !FatalError)
{
ereport(DEBUG2,
(errmsg_internal("sending %s to process %d",
(SendStop ? "SIGSTOP" : "SIGQUIT"),
! (int) AutoVacPID)));
! signal_child(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT));
}
/*
--- 2732,2747 ----
signal_child(WalReceiverPID, (SendStop ? SIGSTOP : SIGQUIT));
}
! /* Take care of the coordinator too */
! if (pid == CoordinatorPID)
! CoordinatorPID = 0;
! else if (CoordinatorPID != 0 && !FatalError)
{
ereport(DEBUG2,
(errmsg_internal("sending %s to process %d",
(SendStop ? "SIGSTOP" : "SIGQUIT"),
! (int) CoordinatorPID)));
! signal_child(CoordinatorPID, (SendStop ? SIGSTOP : SIGQUIT));
}
/*
*************** PostmasterStateMachine(void)
*** 2887,2893 ****
{
/*
* PM_WAIT_BACKENDS state ends when we have no regular backends
! * (including autovac workers) and no walwriter or autovac launcher.
* If we are doing crash recovery then we expect the bgwriter to exit
* too, otherwise not. The archiver, stats, and syslogger processes
* are disregarded since they are not connected to shared memory; we
--- 2887,2893 ----
{
/*
* PM_WAIT_BACKENDS state ends when we have no regular backends
! * (including background workers) and no walwriter or coordinator.
* If we are doing crash recovery then we expect the bgwriter to exit
* too, otherwise not. The archiver, stats, and syslogger processes
* are disregarded since they are not connected to shared memory; we
*************** PostmasterStateMachine(void)
*** 2900,2906 ****
WalReceiverPID == 0 &&
(BgWriterPID == 0 || !FatalError) &&
WalWriterPID == 0 &&
! AutoVacPID == 0)
{
if (FatalError)
{
--- 2900,2906 ----
WalReceiverPID == 0 &&
(BgWriterPID == 0 || !FatalError) &&
WalWriterPID == 0 &&
! CoordinatorPID == 0)
{
if (FatalError)
{
*************** PostmasterStateMachine(void)
*** 2995,3001 ****
Assert(WalReceiverPID == 0);
Assert(BgWriterPID == 0);
Assert(WalWriterPID == 0);
! Assert(AutoVacPID == 0);
/* syslogger is not considered here */
pmState = PM_NO_CHILDREN;
}
--- 2995,3001 ----
Assert(WalReceiverPID == 0);
Assert(BgWriterPID == 0);
Assert(WalWriterPID == 0);
! Assert(CoordinatorPID == 0);
/* syslogger is not considered here */
pmState = PM_NO_CHILDREN;
}
*************** SignalSomeChildren(int signal, int targe
*** 3120,3128 ****
if (bp->dead_end)
continue;
! if (!(target & BACKEND_TYPE_NORMAL) && !bp->is_autovacuum)
continue;
! if (!(target & BACKEND_TYPE_AUTOVAC) && bp->is_autovacuum)
continue;
if (!(target & BACKEND_TYPE_WALSND) &&
IsPostmasterChildWalSender(bp->child_slot))
--- 3120,3128 ----
if (bp->dead_end)
continue;
! if (!(target & BACKEND_TYPE_NORMAL) && !bp->is_bgworker)
continue;
! if (!(target & BACKEND_TYPE_AUTOVAC) && bp->is_bgworker)
continue;
if (!(target & BACKEND_TYPE_WALSND) &&
IsPostmasterChildWalSender(bp->child_slot))
*************** SignalSomeChildren(int signal, int targe
*** 3142,3148 ****
*
* returns: STATUS_ERROR if the fork failed, STATUS_OK otherwise.
*
! * Note: if you change this code, also consider StartAutovacuumWorker.
*/
static int
BackendStartup(Port *port)
--- 3142,3148 ----
*
* returns: STATUS_ERROR if the fork failed, STATUS_OK otherwise.
*
! * Note: if you change this code, also consider StartBackgroundWorker.
*/
static int
BackendStartup(Port *port)
*************** BackendStartup(Port *port)
*** 3242,3248 ****
* of backends.
*/
bn->pid = pid;
! bn->is_autovacuum = false;
DLInitElem(&bn->elem, bn);
DLAddHead(BackendList, &bn->elem);
#ifdef EXEC_BACKEND
--- 3242,3248 ----
* of backends.
*/
bn->pid = pid;
! bn->is_bgworker = false;
DLInitElem(&bn->elem, bn);
DLAddHead(BackendList, &bn->elem);
#ifdef EXEC_BACKEND
*************** SubPostmasterMain(int argc, char *argv[]
*** 3931,3946 ****
* same address the postmaster used.
*/
if (strcmp(argv[1], "--forkbackend") == 0 ||
! strcmp(argv[1], "--forkavlauncher") == 0 ||
! strcmp(argv[1], "--forkavworker") == 0 ||
strcmp(argv[1], "--forkboot") == 0)
PGSharedMemoryReAttach();
! /* autovacuum needs this set before calling InitProcess */
! if (strcmp(argv[1], "--forkavlauncher") == 0)
! AutovacuumLauncherIAm();
! if (strcmp(argv[1], "--forkavworker") == 0)
! AutovacuumWorkerIAm();
/*
* Start our win32 signal implementation. This has to be done after we
--- 3931,3949 ----
* same address the postmaster used.
*/
if (strcmp(argv[1], "--forkbackend") == 0 ||
! strcmp(argv[1], "--forkcoordinator") == 0 ||
! strcmp(argv[1], "--forkbgworker") == 0 ||
strcmp(argv[1], "--forkboot") == 0)
PGSharedMemoryReAttach();
! /*
! * Background workers and the coordinator need this set before calling
! * InitProcess.
! */
! if (strcmp(argv[1], "--forkcoordinator") == 0)
! CoordinatorIAm();
! if (strcmp(argv[1], "--forkbgworker") == 0)
! BackgroundWorkerIAm();
/*
* Start our win32 signal implementation. This has to be done after we
*************** SubPostmasterMain(int argc, char *argv[]
*** 4037,4043 ****
AuxiliaryProcessMain(argc - 2, argv + 2);
proc_exit(0);
}
! if (strcmp(argv[1], "--forkavlauncher") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
--- 4040,4046 ----
AuxiliaryProcessMain(argc - 2, argv + 2);
proc_exit(0);
}
! if (strcmp(argv[1], "--forkcoordinator") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
*************** SubPostmasterMain(int argc, char *argv[]
*** 4051,4060 ****
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
! AutoVacLauncherMain(argc - 2, argv + 2);
proc_exit(0);
}
! if (strcmp(argv[1], "--forkavworker") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
--- 4054,4063 ----
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
! CoordinatorMain(argc - 2, argv + 2);
proc_exit(0);
}
! if (strcmp(argv[1], "--forkbgworker") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
*************** SubPostmasterMain(int argc, char *argv[]
*** 4068,4074 ****
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
! AutoVacWorkerMain(argc - 2, argv + 2);
proc_exit(0);
}
if (strcmp(argv[1], "--forkarch") == 0)
--- 4071,4077 ----
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
! BackgroundWorkerMain(argc - 2, argv + 2);
proc_exit(0);
}
if (strcmp(argv[1], "--forkarch") == 0)
*************** sigusr1_handler(SIGNAL_ARGS)
*** 4190,4199 ****
signal_child(SysLoggerPID, SIGUSR1);
}
! if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER))
{
! /* The autovacuum launcher wants us to start a worker process. */
! StartAutovacuumWorker();
}
if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER) &&
--- 4193,4202 ----
signal_child(SysLoggerPID, SIGUSR1);
}
! if (CheckPostmasterSignal(PMSIGNAL_START_BGWORKER))
{
! /* The coordinator wants us to start a worker process. */
! StartBgWorker();
}
if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER) &&
*************** CountChildren(int target)
*** 4313,4321 ****
if (bp->dead_end)
continue;
! if (!(target & BACKEND_TYPE_NORMAL) && !bp->is_autovacuum)
continue;
! if (!(target & BACKEND_TYPE_AUTOVAC) && bp->is_autovacuum)
continue;
if (!(target & BACKEND_TYPE_WALSND) &&
IsPostmasterChildWalSender(bp->child_slot))
--- 4316,4324 ----
if (bp->dead_end)
continue;
! if (!(target & BACKEND_TYPE_NORMAL) && !bp->is_bgworker)
continue;
! if (!(target & BACKEND_TYPE_AUTOVAC) && bp->is_bgworker)
continue;
if (!(target & BACKEND_TYPE_WALSND) &&
IsPostmasterChildWalSender(bp->child_slot))
*************** StartChildProcess(AuxProcType type)
*** 4431,4438 ****
}
/*
! * StartAutovacuumWorker
! * Start an autovac worker process.
*
* This function is here because it enters the resulting PID into the
* postmaster's private backends list.
--- 4434,4441 ----
}
/*
! * StartBgWorker
! * Start a background worker process.
*
* This function is here because it enters the resulting PID into the
* postmaster's private backends list.
*************** static void
*** 4440,4453 ****
* NB -- this code very roughly matches BackendStartup.
*/
static void
! StartAutovacuumWorker(void)
{
Backend *bn;
/*
* If not in condition to run a process, don't try, but handle it like a
* fork failure. This does not normally happen, since the signal is only
! * supposed to be sent by autovacuum launcher when it's OK to do it, but
* we have to check to avoid race-condition problems during DB state
* changes.
*/
--- 4443,4456 ----
* NB -- this code very roughly matches BackendStartup.
*/
static void
! StartBgWorker(void)
{
Backend *bn;
/*
* If not in condition to run a process, don't try, but handle it like a
* fork failure. This does not normally happen, since the signal is only
! * supposed to be sent by the coordinator when it's OK to do it, but
* we have to check to avoid race-condition problems during DB state
* changes.
*/
*************** StartAutovacuumWorker(void)
*** 4458,4478 ****
{
/*
* Compute the cancel key that will be assigned to this session.
! * We probably don't need cancel keys for autovac workers, but
* we'd better have something random in the field to prevent
* unfriendly people from sending cancels to them.
*/
MyCancelKey = PostmasterRandom();
bn->cancel_key = MyCancelKey;
! /* Autovac workers are not dead_end and need a child slot */
bn->dead_end = false;
bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot();
! bn->pid = StartAutoVacWorker();
if (bn->pid > 0)
{
! bn->is_autovacuum = true;
DLInitElem(&bn->elem, bn);
DLAddHead(BackendList, &bn->elem);
#ifdef EXEC_BACKEND
--- 4461,4481 ----
{
/*
* Compute the cancel key that will be assigned to this session.
! * We probably don't need cancel keys for background workers, but
* we'd better have something random in the field to prevent
* unfriendly people from sending cancels to them.
*/
MyCancelKey = PostmasterRandom();
bn->cancel_key = MyCancelKey;
! /* Background workers are not dead_end and need a child slot */
bn->dead_end = false;
bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot();
! bn->pid = StartBackgroundWorker();
if (bn->pid > 0)
{
! bn->is_bgworker = true;
DLInitElem(&bn->elem, bn);
DLAddHead(BackendList, &bn->elem);
#ifdef EXEC_BACKEND
*************** StartAutovacuumWorker(void)
*** 4484,4490 ****
/*
* fork failed, fall through to report -- actual error message was
! * logged by StartAutoVacWorker
*/
(void) ReleasePostmasterChildSlot(bn->child_slot);
free(bn);
--- 4487,4493 ----
/*
* fork failed, fall through to report -- actual error message was
! * logged by StartBackgroundWorker
*/
(void) ReleasePostmasterChildSlot(bn->child_slot);
free(bn);
*************** StartAutovacuumWorker(void)
*** 4501,4508 ****
* avoid a ping-pong signalling in quick succession between coordinator
* and postmaster in case things get ugly.
*/
! if (AutoVacPID != 0)
! avlauncher_needs_signal = true;
}
/*
--- 4504,4511 ----
* avoid a ping-pong signalling in quick succession between coordinator
* and postmaster in case things get ugly.
*/
! if (CoordinatorPID != 0)
! coordinator_needs_signal = true;
}
/*
============================================================
*** src/backend/storage/ipc/ipc.c 304a8cf3658db251480c2b4517206c21b5bac40d
--- src/backend/storage/ipc/ipc.c af20d2d3315ef31aa41441a3e77b8b975ee1a890
*************** proc_exit(int code)
*** 121,127 ****
*/
char gprofDirName[32];
! if (IsAutoVacuumWorkerProcess())
snprintf(gprofDirName, 32, "gprof/avworker");
else
snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
--- 121,127 ----
*/
char gprofDirName[32];
! if (IsBackgroundWorkerProcess())
snprintf(gprofDirName, 32, "gprof/avworker");
else
snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
============================================================
*** src/backend/storage/ipc/ipci.c 1e5026e411d3728825b8e18dc01a9a0ec9ce974d
--- src/backend/storage/ipc/ipci.c 7e32569fd32941d7c26800f3077b0ff94e210f9e
*************** CreateSharedMemoryAndSemaphores(bool mak
*** 120,126 ****
size = add_size(size, PMSignalShmemSize());
size = add_size(size, ProcSignalShmemSize());
size = add_size(size, BgWriterShmemSize());
! size = add_size(size, AutoVacuumShmemSize());
size = add_size(size, WalSndShmemSize());
size = add_size(size, WalRcvShmemSize());
size = add_size(size, BTreeShmemSize());
--- 120,126 ----
size = add_size(size, PMSignalShmemSize());
size = add_size(size, ProcSignalShmemSize());
size = add_size(size, BgWriterShmemSize());
! size = add_size(size, CoordinatorShmemSize());
size = add_size(size, WalSndShmemSize());
size = add_size(size, WalRcvShmemSize());
size = add_size(size, BTreeShmemSize());
*************** CreateSharedMemoryAndSemaphores(bool mak
*** 226,232 ****
PMSignalShmemInit();
ProcSignalShmemInit();
BgWriterShmemInit();
! AutoVacuumShmemInit();
WalSndShmemInit();
WalRcvShmemInit();
--- 226,232 ----
PMSignalShmemInit();
ProcSignalShmemInit();
BgWriterShmemInit();
! CoordinatorShmemInit();
WalSndShmemInit();
WalRcvShmemInit();
============================================================
*** src/backend/storage/lmgr/proc.c bbd84c0cdc85587bd4e04f1b69ead6ea11bb08dd
--- src/backend/storage/lmgr/proc.c 227fffe14ecf0833f313fc7eba58a45e968210fe
*************** ProcGlobalSemas(void)
*** 143,149 ****
* running out when trying to start another backend is a common failure.
* So, now we grab enough semaphores to support the desired max number
* of backends immediately at initialization --- if the sysadmin has set
! * MaxConnections or autovacuum_max_workers higher than his kernel will
* support, he'll find out sooner rather than later.
*
* Another reason for creating semaphores here is that the semaphore
--- 143,149 ----
* running out when trying to start another backend is a common failure.
* So, now we grab enough semaphores to support the desired max number
* of backends immediately at initialization --- if the sysadmin has set
! * MaxConnections or max_background_workers higher than his kernel will
* support, he'll find out sooner rather than later.
*
* Another reason for creating semaphores here is that the semaphore
*************** InitProcGlobal(void)
*** 204,216 ****
*
* Note: the "+1" here accounts for the autovac launcher
*/
! procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers + 1) * sizeof(PGPROC));
if (!procs)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
! MemSet(procs, 0, (autovacuum_max_workers + 1) * sizeof(PGPROC));
! for (i = 0; i < autovacuum_max_workers + 1; i++)
{
PGSemaphoreCreate(&(procs[i].sem));
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
--- 204,216 ----
*
* Note: the "+1" here accounts for the autovac launcher
*/
! procs = (PGPROC *) ShmemAlloc((max_background_workers + 1) * sizeof(PGPROC));
if (!procs)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
! MemSet(procs, 0, (max_background_workers + 1) * sizeof(PGPROC));
! for (i = 0; i < max_background_workers + 1; i++)
{
PGSemaphoreCreate(&(procs[i].sem));
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
*************** InitProcess(void)
*** 263,276 ****
set_spins_per_delay(procglobal->spins_per_delay);
! if (IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess())
MyProc = procglobal->autovacFreeProcs;
else
MyProc = procglobal->freeProcs;
if (MyProc != NULL)
{
! if (IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess())
procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next;
else
procglobal->freeProcs = (PGPROC *) MyProc->links.next;
--- 263,276 ----
set_spins_per_delay(procglobal->spins_per_delay);
! if (IsCoordinatorProcess() || IsBackgroundWorkerProcess())
MyProc = procglobal->autovacFreeProcs;
else
MyProc = procglobal->freeProcs;
if (MyProc != NULL)
{
! if (IsCoordinatorProcess() || IsBackgroundWorkerProcess())
procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next;
else
procglobal->freeProcs = (PGPROC *) MyProc->links.next;
*************** InitProcess(void)
*** 296,302 ****
* cleaning up. (XXX autovac launcher currently doesn't participate in
* this; it probably should.)
*/
! if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess())
{
if (am_walsender)
MarkPostmasterChildWalSender();
--- 296,302 ----
* cleaning up. (XXX autovac launcher currently doesn't participate in
* this; it probably should.)
*/
! if (IsUnderPostmaster && !IsCoordinatorProcess())
{
if (am_walsender)
MarkPostmasterChildWalSender();
*************** InitProcess(void)
*** 321,327 ****
MyProc->inCommit = false;
MyProc->vacuumFlags = 0;
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
! if (IsAutoVacuumWorkerProcess())
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
--- 321,327 ----
MyProc->inCommit = false;
MyProc->vacuumFlags = 0;
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
! if (IsBackgroundWorkerProcess())
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
*************** ProcKill(int code, Datum arg)
*** 682,688 ****
SpinLockAcquire(ProcStructLock);
/* Return PGPROC structure (and semaphore) to appropriate freelist */
! if (IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess())
{
MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs;
procglobal->autovacFreeProcs = MyProc;
--- 682,688 ----
SpinLockAcquire(ProcStructLock);
/* Return PGPROC structure (and semaphore) to appropriate freelist */
! if (IsCoordinatorProcess() || IsBackgroundWorkerProcess())
{
MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs;
procglobal->autovacFreeProcs = MyProc;
*************** ProcKill(int code, Datum arg)
*** 706,712 ****
* way, so tell the postmaster we've cleaned up acceptably well. (XXX
* autovac launcher should be included here someday)
*/
! if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess())
MarkPostmasterChildInactive();
}
--- 706,712 ----
* way, so tell the postmaster we've cleaned up acceptably well. (XXX
* autovac launcher should be included here someday)
*/
! if (IsUnderPostmaster && !IsCoordinatorProcess())
MarkPostmasterChildInactive();
}
============================================================
*** src/backend/tcop/postgres.c 778b93a7067312d73d4c68561d8fa23476c0a292
--- src/backend/tcop/postgres.c bbc0e7db5e6aae98d7077b6321089f4262547ca9
*************** ProcessInterrupts(void)
*** 2891,2900 ****
/* As in quickdie, don't risk sending to client during auth */
if (ClientAuthInProgress && whereToSendOutput == DestRemote)
whereToSendOutput = DestNone;
! if (IsAutoVacuumWorkerProcess())
ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN),
! errmsg("terminating autovacuum process due to administrator command")));
else if (RecoveryConflictPending && RecoveryConflictRetryable)
ereport(FATAL,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
--- 2891,2900 ----
/* As in quickdie, don't risk sending to client during auth */
if (ClientAuthInProgress && whereToSendOutput == DestRemote)
whereToSendOutput = DestNone;
! if (IsBackgroundWorkerProcess())
ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN),
! errmsg("terminating background worker process due to administrator command")));
else if (RecoveryConflictPending && RecoveryConflictRetryable)
ereport(FATAL,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
*************** ProcessInterrupts(void)
*** 2934,2940 ****
(errcode(ERRCODE_QUERY_CANCELED),
errmsg("canceling statement due to statement timeout")));
}
! if (IsAutoVacuumWorkerProcess())
{
/* FIXME: make sure this works fine for all background jobs */
ImmediateInterruptOK = false; /* not idle anymore */
--- 2934,2940 ----
(errcode(ERRCODE_QUERY_CANCELED),
errmsg("canceling statement due to statement timeout")));
}
! if (IsBackgroundWorkerProcess())
{
/* FIXME: make sure this works fine for all background jobs */
ImmediateInterruptOK = false; /* not idle anymore */
============================================================
*** src/backend/utils/init/globals.c 626dcd5939ff8882d155015f0aecae78e2945728
--- src/backend/utils/init/globals.c 941f73a44a2a558c326344246d35740bf320fef8
*************** int maintenance_work_mem = 16384;
*** 101,107 ****
/*
* Primary determinants of sizes of shared-memory structures. MaxBackends is
! * MaxConnections + autovacuum_max_workers + 1 (it is computed by the GUC
* assign hooks for those variables):
*/
int NBuffers = 1000;
--- 101,107 ----
/*
* Primary determinants of sizes of shared-memory structures. MaxBackends is
! * MaxConnections + max_background_workers + 1 (it is computed by the GUC
* assign hooks for those variables):
*/
int NBuffers = 1000;
============================================================
*** src/backend/utils/init/miscinit.c 264963c6cfa0b082b09d6bba8b8d7df6c0f99eb5
--- src/backend/utils/init/miscinit.c d3022f8ecf3b3b7084e064ac2661d1ff7ec1c560
*************** InitializeSessionUserIdStandalone(void)
*** 481,487 ****
* This function should only be called in single-user mode and in
* autovacuum workers.
*/
! AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess());
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
--- 481,487 ----
* This function should only be called in single-user mode and in
* autovacuum workers.
*/
! AssertState(!IsUnderPostmaster || IsBackgroundWorkerProcess());
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
============================================================
*** src/backend/utils/init/postinit.c 97b5d8e74b7361ae6f1776c60bc1f1977c2c31bc
--- src/backend/utils/init/postinit.c 7516795aa54c52d299b38a133329aa1ac8449a10
*************** CheckMyDatabase(const char *name, bool a
*** 281,287 ****
*
* We do not enforce them for autovacuum worker processes either.
*/
! if (IsUnderPostmaster && !IsAutoVacuumWorkerProcess())
{
/*
* Check that the database is currently allowing connections.
--- 281,287 ----
*
* We do not enforce them for autovacuum worker processes either.
*/
! if (IsUnderPostmaster && !IsBackgroundWorkerProcess())
{
/*
* Check that the database is currently allowing connections.
*************** InitPostgres(const char *in_dbname, Oid
*** 569,575 ****
on_shmem_exit(ShutdownPostgres, 0);
/* The autovacuum launcher is done here */
! if (IsAutoVacuumLauncherProcess())
return;
/*
--- 569,575 ----
on_shmem_exit(ShutdownPostgres, 0);
/* The autovacuum launcher is done here */
! if (IsCoordinatorProcess())
return;
/*
*************** InitPostgres(const char *in_dbname, Oid
*** 593,599 ****
* In standalone mode and in autovacuum worker processes, we use a fixed
* ID, otherwise we figure it out from the authenticated user name.
*/
! if (bootstrap || IsAutoVacuumWorkerProcess())
{
InitializeSessionUserIdStandalone();
am_superuser = true;
--- 593,599 ----
* In standalone mode and in autovacuum worker processes, we use a fixed
* ID, otherwise we figure it out from the authenticated user name.
*/
! if (bootstrap || IsBackgroundWorkerProcess())
{
InitializeSessionUserIdStandalone();
am_superuser = true;
============================================================
*** src/backend/access/transam/xlog.c 35715aec89ea13b429cffeb513fd439d1138cf0a
--- src/backend/access/transam/xlog.c 769d4de171e9c891a1cfb4516ff7a3e88f66033e
*************** CheckRequiredParameterValues(void)
*** 5660,5666 ****
(errmsg("hot standby is not possible because wal_level was not set to \"hot_standby\" on the master server"),
errhint("Either set wal_level to \"hot_standby\" on the master, or turn off hot_standby here.")));
! /* We ignore autovacuum_max_workers when we make this test. */
RecoveryRequiresIntParameter("max_connections",
MaxConnections,
ControlFile->MaxConnections);
--- 5660,5666 ----
(errmsg("hot standby is not possible because wal_level was not set to \"hot_standby\" on the master server"),
errhint("Either set wal_level to \"hot_standby\" on the master, or turn off hot_standby here.")));
! /* We ignore max__background_workers when we make this test. */
RecoveryRequiresIntParameter("max_connections",
MaxConnections,
ControlFile->MaxConnections);
============================================================
*** src/backend/commands/analyze.c 106a0d69fd64ba23ac9cb7d022ed85673515b8a5
--- src/backend/commands/analyze.c 618166236ea3b1f37c763478c0000bf14654717c
*************** do_analyze_rel(Relation onerel, VacuumSt
*** 310,316 ****
save_nestlevel = NewGUCNestLevel();
/* measure elapsed time iff autovacuum logging requires it */
! if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
pg_rusage_init(&ru0);
if (Log_autovacuum_min_duration > 0)
--- 310,316 ----
save_nestlevel = NewGUCNestLevel();
/* measure elapsed time iff autovacuum logging requires it */
! if (IsBackgroundWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
pg_rusage_init(&ru0);
if (Log_autovacuum_min_duration > 0)
*************** cleanup:
*** 612,618 ****
vac_close_indexes(nindexes, Irel, NoLock);
/* Log the action if appropriate */
! if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
if (Log_autovacuum_min_duration == 0 ||
TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
--- 612,618 ----
vac_close_indexes(nindexes, Irel, NoLock);
/* Log the action if appropriate */
! if (IsBackgroundWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
if (Log_autovacuum_min_duration == 0 ||
TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
============================================================
*** src/backend/utils/misc/guc.c b1a0bdd9b727094182159680278763a09f3ded9c
--- src/backend/utils/misc/guc.c 194be259610536302033f04f41fcd59e83620e77
*************** static bool assign_maxconnections(int ne
*** 170,176 ****
static const char *show_tcp_keepalives_interval(void);
static const char *show_tcp_keepalives_count(void);
static bool assign_maxconnections(int newval, bool doit, GucSource source);
! static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source);
static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source);
static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source);
static const char *assign_application_name(const char *newval, bool doit, GucSource source);
--- 170,176 ----
static const char *show_tcp_keepalives_interval(void);
static const char *show_tcp_keepalives_count(void);
static bool assign_maxconnections(int newval, bool doit, GucSource source);
! static bool assign_max_background_workers(int newval, bool doit, GucSource source);
static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source);
static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source);
static const char *assign_application_name(const char *newval, bool doit, GucSource source);
*************** static struct config_int ConfigureNamesI
*** 1397,1403 ****
* Note: MaxBackends is limited to INT_MAX/4 because some places compute
* 4*MaxBackends without any overflow check. This check is made in
* assign_maxconnections, since MaxBackends is computed as MaxConnections
! * plus autovacuum_max_workers plus one (for the autovacuum launcher).
*
* Likewise we have to limit NBuffers to INT_MAX/2.
*
--- 1397,1403 ----
* Note: MaxBackends is limited to INT_MAX/4 because some places compute
* 4*MaxBackends without any overflow check. This check is made in
* assign_maxconnections, since MaxBackends is computed as MaxConnections
! * plus max_background_workers plus one (for the autovacuum launcher).
*
* Likewise we have to limit NBuffers to INT_MAX/2.
*
*************** static struct config_int ConfigureNamesI
*** 1994,2005 ****
},
{
/* see max_connections */
! {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
NULL
},
! &autovacuum_max_workers,
! 3, 1, INT_MAX / 4, assign_autovacuum_max_workers, NULL
},
{
--- 1994,2005 ----
},
{
/* see max_connections */
! {"max_background_workers", PGC_POSTMASTER, AUTOVACUUM,
gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
NULL
},
! &max_background_workers,
! 3, 1, INT_MAX / 4, assign_max_background_workers, NULL
},
{
*************** assign_maxconnections(int newval, bool d
*** 7972,7988 ****
static bool
assign_maxconnections(int newval, bool doit, GucSource source)
{
! if (newval + autovacuum_max_workers + 1 > INT_MAX / 4)
return false;
if (doit)
! MaxBackends = newval + autovacuum_max_workers + 1;
return true;
}
static bool
! assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
{
if (MaxConnections + newval + 1 > INT_MAX / 4)
return false;
--- 7972,7988 ----
static bool
assign_maxconnections(int newval, bool doit, GucSource source)
{
! if (newval + max_background_workers + 1 > INT_MAX / 4)
return false;
if (doit)
! MaxBackends = newval + max_background_workers + 1;
return true;
}
static bool
! assign_max_background_workers(int newval, bool doit, GucSource source)
{
if (MaxConnections + newval + 1 > INT_MAX / 4)
return false;
============================================================
*** src/backend/utils/misc/postgresql.conf.sample 14a99f6b70482f481ccd82dad86e31a9421c9336
--- src/backend/utils/misc/postgresql.conf.sample d9acfb47e04263a3caae6ec5e5c04316f3a7f176
***************
*** 404,413 ****
#------------------------------------------------------------------------------
! # BACKGROUND WORKER PARAMETERS (including autovacuum)
#------------------------------------------------------------------------------
! #autovacuum_max_workers = 3 # max number of background helper
# subprocesses (for all databases)
#min_spare_background_helpers = 0 # min spare workers to prefork and
--- 404,413 ----
#------------------------------------------------------------------------------
! # BACKGROUND WORKER PARAMETERS (includes autovacuum)
#------------------------------------------------------------------------------
! #max_background_workers = 3 # max number of background helper
# subprocesses (for all databases)
#min_spare_background_helpers = 0 # min spare workers to prefork and
============================================================
*** src/backend/postmaster/pgstat.c cfd69500a4ad774f69f30ab3a759d090fbb09e6a
--- src/backend/postmaster/pgstat.c 6f82a2553021742674644dccbb7072db58aa3711
*************** pgstat_report_vacuum(Oid tableoid, bool
*** 1256,1262 ****
msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = tableoid;
msg.m_adopt_counts = adopt_counts;
! msg.m_autovacuum = IsAutoVacuumWorkerProcess();
msg.m_vacuumtime = GetCurrentTimestamp();
msg.m_tuples = tuples;
pgstat_send(&msg, sizeof(msg));
--- 1256,1262 ----
msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = tableoid;
msg.m_adopt_counts = adopt_counts;
! msg.m_bgworker = IsBackgroundWorkerProcess();
msg.m_vacuumtime = GetCurrentTimestamp();
msg.m_tuples = tuples;
pgstat_send(&msg, sizeof(msg));
*************** pgstat_report_analyze(Relation rel, bool
*** 1307,1313 ****
msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = RelationGetRelid(rel);
msg.m_adopt_counts = adopt_counts;
! msg.m_autovacuum = IsAutoVacuumWorkerProcess();
msg.m_analyzetime = GetCurrentTimestamp();
msg.m_live_tuples = livetuples;
msg.m_dead_tuples = deadtuples;
--- 1307,1313 ----
msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = RelationGetRelid(rel);
msg.m_adopt_counts = adopt_counts;
! msg.m_bgworker = IsBackgroundWorkerProcess();
msg.m_analyzetime = GetCurrentTimestamp();
msg.m_live_tuples = livetuples;
msg.m_dead_tuples = deadtuples;
*************** backend_read_statsfile(void)
*** 3669,3675 ****
* PGSTAT_STAT_INTERVAL; and we don't want to lie to the collector about
* what our cutoff time really is.
*/
! if (IsAutoVacuumWorkerProcess())
min_ts = TimestampTzPlusMilliseconds(GetCurrentTimestamp(),
-PGSTAT_RETRY_DELAY);
else
--- 3669,3675 ----
* PGSTAT_STAT_INTERVAL; and we don't want to lie to the collector about
* what our cutoff time really is.
*/
! if (IsBackgroundWorkerProcess())
min_ts = TimestampTzPlusMilliseconds(GetCurrentTimestamp(),
-PGSTAT_RETRY_DELAY);
else
*************** backend_read_statsfile(void)
*** 3700,3706 ****
elog(WARNING, "pgstat wait timeout");
/* Autovacuum launcher wants stats about all databases */
! if (IsAutoVacuumLauncherProcess())
pgStatDBHash = pgstat_read_statsfile(InvalidOid, false);
else
pgStatDBHash = pgstat_read_statsfile(MyDatabaseId, false);
--- 3700,3706 ----
elog(WARNING, "pgstat wait timeout");
/* Autovacuum launcher wants stats about all databases */
! if (IsCoordinatorProcess())
pgStatDBHash = pgstat_read_statsfile(InvalidOid, false);
else
pgStatDBHash = pgstat_read_statsfile(MyDatabaseId, false);
*************** pgstat_recv_vacuum(PgStat_MsgVacuum *msg
*** 4070,4076 ****
/* Resetting dead_tuples to 0 is an approximation ... */
tabentry->n_dead_tuples = 0;
! if (msg->m_autovacuum)
tabentry->autovac_vacuum_timestamp = msg->m_vacuumtime;
else
tabentry->vacuum_timestamp = msg->m_vacuumtime;
--- 4070,4076 ----
/* Resetting dead_tuples to 0 is an approximation ... */
tabentry->n_dead_tuples = 0;
! if (msg->m_bgworker)
tabentry->autovac_vacuum_timestamp = msg->m_vacuumtime;
else
tabentry->vacuum_timestamp = msg->m_vacuumtime;
*************** pgstat_recv_analyze(PgStat_MsgAnalyze *m
*** 4107,4113 ****
*/
tabentry->changes_since_analyze = 0;
! if (msg->m_autovacuum)
tabentry->autovac_analyze_timestamp = msg->m_analyzetime;
else
tabentry->analyze_timestamp = msg->m_analyzetime;
--- 4107,4113 ----
*/
tabentry->changes_since_analyze = 0;
! if (msg->m_bgworker)
tabentry->autovac_analyze_timestamp = msg->m_analyzetime;
else
tabentry->analyze_timestamp = msg->m_analyzetime;
============================================================
*** src/include/pgstat.h 3c935ec633909c2864ad4a79c7a8c830289150d9
--- src/include/pgstat.h eb6b09e66466b9220aad3854e7877d7709b11ffd
*************** typedef struct PgStat_MsgVacuum
*** 322,328 ****
Oid m_databaseid;
Oid m_tableoid;
bool m_adopt_counts;
! bool m_autovacuum;
TimestampTz m_vacuumtime;
PgStat_Counter m_tuples;
} PgStat_MsgVacuum;
--- 322,328 ----
Oid m_databaseid;
Oid m_tableoid;
bool m_adopt_counts;
! bool m_bgworker;
TimestampTz m_vacuumtime;
PgStat_Counter m_tuples;
} PgStat_MsgVacuum;
*************** typedef struct PgStat_MsgAnalyze
*** 339,345 ****
Oid m_databaseid;
Oid m_tableoid;
bool m_adopt_counts;
! bool m_autovacuum;
TimestampTz m_analyzetime;
PgStat_Counter m_live_tuples;
PgStat_Counter m_dead_tuples;
--- 339,345 ----
Oid m_databaseid;
Oid m_tableoid;
bool m_adopt_counts;
! bool m_bgworker;
TimestampTz m_analyzetime;
PgStat_Counter m_live_tuples;
PgStat_Counter m_dead_tuples;
============================================================
*** src/backend/commands/vacuumlazy.c 2a1a3d68a6bdf7d0a558a03d9cec90c586beae3e
--- src/backend/commands/vacuumlazy.c ee705c606001471649559bc45d1676b7c943c3a2
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 157,163 ****
pg_rusage_init(&ru0);
/* measure elapsed time iff autovacuum logging requires it */
! if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
if (vacstmt->options & VACOPT_VERBOSE)
--- 157,163 ----
pg_rusage_init(&ru0);
/* measure elapsed time iff autovacuum logging requires it */
! if (IsBackgroundWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
if (vacstmt->options & VACOPT_VERBOSE)
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 225,231 ****
vacrelstats->rel_tuples);
/* and log the action if appropriate */
! if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
if (Log_autovacuum_min_duration == 0 ||
TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
--- 225,231 ----
vacrelstats->rel_tuples);
/* and log the action if appropriate */
! if (IsBackgroundWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
if (Log_autovacuum_min_duration == 0 ||
TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
============================================================
*** src/include/storage/lwlock.h 2aea3a2fcddca3a9f9eea62f65d08930d221beb5
--- src/include/storage/lwlock.h 961fe3aa8f73e8c722383e33513426a6c5f83ba4
*************** typedef enum LWLockId
*** 64,71 ****
TablespaceCreateLock,
BtreeVacuumLock,
AddinShmemInitLock,
! AutovacuumLock,
! AutovacuumScheduleLock,
CoordinatorDatabasesLock,
SyncScanLock,
RelationMappingLock,
--- 64,71 ----
TablespaceCreateLock,
BtreeVacuumLock,
AddinShmemInitLock,
! WorkerInfoLock,
! WorkerScheduleLock,
CoordinatorDatabasesLock,
SyncScanLock,
RelationMappingLock,
============================================================
*** src/include/storage/pmsignal.h c8113d31e2e76fc64ad82209ff2fb8aea91f68b3
--- src/include/storage/pmsignal.h 0d704becf5cfcbacf1d614e025f3622d76b489fc
*************** typedef enum
*** 26,32 ****
PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */
PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */
PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */
! PMSIGNAL_START_AUTOVAC_WORKER, /* start an autovacuum worker */
PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */
NUM_PMSIGNALS /* Must be last value of enum! */
--- 26,32 ----
PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */
PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */
PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */
! PMSIGNAL_START_BGWORKER, /* start a background worker process */
PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */
NUM_PMSIGNALS /* Must be last value of enum! */
============================================================
*** src/backend/postmaster/autovacuum.c ca02f9e08a1dbe34ff8049c0d51cc76594fb16a0
--- src/backend/postmaster/autovacuum.c 9f0dd25e08c15c2cf3989e24996554fa94c99f08
*************** bool autovacuum_enabled = false;
*** 105,111 ****
* GUC parameters
*/
bool autovacuum_enabled = false;
! int autovacuum_max_workers;
int min_spare_background_workers;
int max_spare_background_workers;
int autovacuum_naptime;
--- 105,111 ----
* GUC parameters
*/
bool autovacuum_enabled = false;
! int max_background_workers;
int min_spare_background_workers;
int max_spare_background_workers;
int autovacuum_naptime;
*************** int Log_autovacuum_min_duration = -1;
*** 126,134 ****
/* the minimum allowed time between two awakenings of the launcher */
#define MIN_AUTOVAC_SLEEPTIME 100.0 /* milliseconds */
! /* Flags to tell if we are in an autovacuum process */
! static bool am_autovacuum_launcher = false;
! static bool am_autovacuum_worker = false;
/* Flags set by signal handlers */
static volatile sig_atomic_t got_SIGHUP = false;
--- 126,134 ----
/* the minimum allowed time between two awakenings of the launcher */
#define MIN_AUTOVAC_SLEEPTIME 100.0 /* milliseconds */
! /* Flags to tell if we are in a coordinator or background worker process */
! static bool am_coordinator = false;
! static bool am_background_worker = false;
/* Flags set by signal handlers */
static volatile sig_atomic_t got_SIGHUP = false;
*************** static int default_freeze_table_age;
*** 143,150 ****
static int default_freeze_table_age;
/* Memory contexts for long-lived data */
! static MemoryContext AutovacLauncherMemCxt;
! static MemoryContext AutovacWorkerMemCxt;
/* job handling routines */
static void bgworker_job_initialize(worker_state new_state);
--- 143,150 ----
static int default_freeze_table_age;
/* Memory contexts for long-lived data */
! static MemoryContext CoordinatorMemCxt;
! static MemoryContext BgWorkerMemCxt;
/* job handling routines */
static void bgworker_job_initialize(worker_state new_state);
*************** typedef struct autovac_table
*** 199,226 ****
} autovac_table;
/*-------------
! * The main autovacuum shmem struct. On shared memory we store this main
! * struct and the array of WorkerInfo structs. This struct keeps:
*
! * av_launcherid the BackendId of the autovacuum launcher
! * av_freeWorkers the WorkerInfo freelist
! * av_runningWorkers the WorkerInfo non-free queue
! * av_startingWorker pointer to WorkerInfo currently being started (cleared by
! * the worker itself as soon as it's up and running)
*
! * This struct is protected by AutovacuumLock, except for parts of the worker
* list (see above).
*-------------
*/
typedef struct
{
! BackendId av_launcherid;
! WorkerInfo av_freeWorkers;
! SHM_QUEUE av_runningWorkers;
! WorkerInfo av_startingWorker;
! } AutoVacuumShmemStruct;
! static AutoVacuumShmemStruct *AutoVacuumShmem;
/*
* Table of databases with at least one connected worker, resides in shared
--- 199,227 ----
} autovac_table;
/*-------------
! * The main background worker shmem struct. On shared memory we store this
! * main struct and the array of WorkerInfo structs. This struct keeps:
*
! * co_coordinatorid the BackendId of the coordinator
! * co_freeWorkers the WorkerInfo freelist
! * co_runningWorkers the WorkerInfo non-free queue
! * co_startingWorker pointer to WorkerInfo currently being started
! * (cleared by the worker itself as soon as it's up and
! * running)
*
! * This struct is protected by WorkerInfoLock, except for parts of the worker
* list (see above).
*-------------
*/
typedef struct
{
! BackendId co_coordinatorid;
! WorkerInfo co_freeWorkers;
! SHM_QUEUE co_runningWorkers;
! WorkerInfo co_startingWorker;
! } CoordinatorShmemStruct;
! static CoordinatorShmemStruct *CoordinatorShmem;
/*
* Table of databases with at least one connected worker, resides in shared
*************** static WorkerInfo terminatable_worker =
*** 237,248 ****
static WorkerInfo terminatable_worker = NULL;
#ifdef EXEC_BACKEND
! static pid_t avlauncher_forkexec(void);
! static pid_t avworker_forkexec(void);
#endif
! NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
static void handle_imessage(IMessage *msg);
! NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]);
static void init_co_database(co_database *codb);
static co_database *get_co_database(Oid dboid);
--- 238,249 ----
static WorkerInfo terminatable_worker = NULL;
#ifdef EXEC_BACKEND
! static pid_t coordinator_forkexec(void);
! static pid_t bgworker_forkexec(void);
#endif
! NON_EXEC_STATIC void BackgroundWorkerMain(int argc, char *argv[]);
static void handle_imessage(IMessage *msg);
! NON_EXEC_STATIC void CoordinatorMain(int argc, char *argv[]);
static void init_co_database(co_database *codb);
static co_database *get_co_database(Oid dboid);
*************** static Oid autovacuum_select_database(vo
*** 263,269 ****
static void do_start_worker(Oid dboid);
static Oid autovacuum_select_database(void);
! static void launcher_determine_sleep(bool can_launch, bool recursing,
struct timespec *nap);
static void autovacuum_update_timing(Oid dbid, TimestampTz now);
static List *get_database_list(void);
--- 264,270 ----
static void do_start_worker(Oid dboid);
static Oid autovacuum_select_database(void);
! static void coordinator_determine_sleep(bool can_launch, bool recursing,
struct timespec *nap);
static void autovacuum_update_timing(Oid dbid, TimestampTz now);
static List *get_database_list(void);
*************** decode_worker_state(worker_state state)
*** 312,334 ****
/********************************************************************
! * AUTOVACUUM LAUNCHER CODE
********************************************************************/
#ifdef EXEC_BACKEND
/*
! * forkexec routine for the autovacuum launcher process.
*
* Format up the arglist, then fork and exec.
*/
static pid_t
! avlauncher_forkexec(void)
{
char *av[10];
int ac = 0;
av[ac++] = "postgres";
! av[ac++] = "--forkavlauncher";
av[ac++] = NULL; /* filled in by postmaster_forkexec */
av[ac] = NULL;
--- 313,335 ----
/********************************************************************
! * COORDINATOR CODE
********************************************************************/
#ifdef EXEC_BACKEND
/*
! * forkexec routine for the coordinator process.
*
* Format up the arglist, then fork and exec.
*/
static pid_t
! coordinator_forkexec(void)
{
char *av[10];
int ac = 0;
av[ac++] = "postgres";
! av[ac++] = "--forkcoordinator";
av[ac++] = NULL; /* filled in by postmaster_forkexec */
av[ac] = NULL;
*************** void
*** 341,370 ****
* We need this set from the outside, before InitProcess is called
*/
void
! AutovacuumLauncherIAm(void)
{
! am_autovacuum_launcher = true;
}
#endif
/*
! * Main entry point for autovacuum launcher process, to be called from the
! * postmaster.
*/
int
! StartAutoVacLauncher(void)
{
! pid_t AutoVacPID;
#ifdef EXEC_BACKEND
! switch ((AutoVacPID = avlauncher_forkexec()))
#else
! switch ((AutoVacPID = fork_process()))
#endif
{
case -1:
ereport(LOG,
! (errmsg("could not fork autovacuum launcher process: %m")));
return 0;
#ifndef EXEC_BACKEND
--- 342,370 ----
* We need this set from the outside, before InitProcess is called
*/
void
! CoordinatorIAm(void)
{
! am_coordinator = true;
}
#endif
/*
! * Main entry point for coordinator process, to be called from the postmaster.
*/
int
! StartCoordinator(void)
{
! pid_t CoordinatorPID;
#ifdef EXEC_BACKEND
! switch ((CoordinatorPID = coordinator_forkexec()))
#else
! switch ((CoordinatorPID = fork_process()))
#endif
{
case -1:
ereport(LOG,
! (errmsg("could not fork the coordinator process: %m")));
return 0;
#ifndef EXEC_BACKEND
*************** StartAutoVacLauncher(void)
*** 376,386 ****
/* Lose the postmaster's on-exit routines */
on_exit_reset();
! AutoVacLauncherMain(0, NULL);
break;
#endif
default:
! return (int) AutoVacPID;
}
/* shouldn't get here */
--- 376,386 ----
/* Lose the postmaster's on-exit routines */
on_exit_reset();
! CoordinatorMain(0, NULL);
break;
#endif
default:
! return (int) CoordinatorPID;
}
/* shouldn't get here */
*************** populate_co_databases()
*** 581,590 ****
}
/*
! * Main loop for the autovacuum launcher process.
*/
NON_EXEC_STATIC void
! AutoVacLauncherMain(int argc, char *argv[])
{
sigjmp_buf local_sigjmp_buf;
IMessage *msg = NULL;
--- 581,590 ----
}
/*
! * Main loop for the coordinator process.
*/
NON_EXEC_STATIC void
! CoordinatorMain(int argc, char *argv[])
{
sigjmp_buf local_sigjmp_buf;
IMessage *msg = NULL;
*************** AutoVacLauncherMain(int argc, char *argv
*** 592,598 ****
/* we are a postmaster subprocess now */
IsUnderPostmaster = true;
! am_autovacuum_launcher = true;
/* reset MyProcPid */
MyProcPid = getpid();
--- 592,598 ----
/* we are a postmaster subprocess now */
IsUnderPostmaster = true;
! am_coordinator = true;
/* reset MyProcPid */
MyProcPid = getpid();
*************** AutoVacLauncherMain(int argc, char *argv
*** 601,610 ****
MyStartTime = time(NULL);
/* Identify myself via ps */
! init_ps_display("autovacuum launcher process", "", "", "");
ereport(LOG,
! (errmsg("autovacuum launcher started")));
if (PostAuthDelay)
pg_usleep(PostAuthDelay * 1000000L);
--- 601,610 ----
MyStartTime = time(NULL);
/* Identify myself via ps */
! init_ps_display("coordinator process", "", "", "");
ereport(LOG,
! (errmsg("coordinator started")));
if (PostAuthDelay)
pg_usleep(PostAuthDelay * 1000000L);
*************** AutoVacLauncherMain(int argc, char *argv
*** 613,620 ****
/*
* 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
--- 613,620 ----
/*
* If possible, make this process a group leader, so that the postmaster
! * can signal any child processes too. (coordinator probably never has
! * any child processes, but for consistency we make all postmaster child
* processes do this.)
*/
#ifdef HAVE_SETSID
*************** AutoVacLauncherMain(int argc, char *argv
*** 662,673 ****
* that we can reset the context during error recovery and thereby avoid
* possible memory leaks.
*/
! AutovacLauncherMemCxt = AllocSetContextCreate(TopMemoryContext,
! "Autovacuum Launcher",
! ALLOCSET_DEFAULT_MINSIZE,
! ALLOCSET_DEFAULT_INITSIZE,
! ALLOCSET_DEFAULT_MAXSIZE);
! MemoryContextSwitchTo(AutovacLauncherMemCxt);
/*
* If an exception is encountered, processing resumes here.
--- 662,673 ----
* that we can reset the context during error recovery and thereby avoid
* possible memory leaks.
*/
! CoordinatorMemCxt = AllocSetContextCreate(TopMemoryContext,
! "Coordinator",
! ALLOCSET_DEFAULT_MINSIZE,
! ALLOCSET_DEFAULT_INITSIZE,
! ALLOCSET_DEFAULT_MAXSIZE);
! MemoryContextSwitchTo(CoordinatorMemCxt);
/*
* If an exception is encountered, processing resumes here.
*************** AutoVacLauncherMain(int argc, char *argv
*** 697,707 ****
* Now return to normal top-level context and clear ErrorContext for
* next time.
*/
! MemoryContextSwitchTo(AutovacLauncherMemCxt);
FlushErrorState();
/* Flush any leaked data in the top-level context */
! MemoryContextResetAndDeleteChildren(AutovacLauncherMemCxt);
/* don't leave dangling pointers to freed memory */
DatabaseListCxt = NULL;
--- 697,707 ----
* Now return to normal top-level context and clear ErrorContext for
* next time.
*/
! MemoryContextSwitchTo(CoordinatorMemCxt);
FlushErrorState();
/* Flush any leaked data in the top-level context */
! MemoryContextResetAndDeleteChildren(CoordinatorMemCxt);
/* don't leave dangling pointers to freed memory */
DatabaseListCxt = NULL;
*************** AutoVacLauncherMain(int argc, char *argv
*** 729,735 ****
/* must unblock signals before calling rebuild_database_list */
PG_SETMASK(&UnBlockSig);
! AutoVacuumShmem->av_launcherid = MyBackendId;
/*
* Initial population of the database list from pg_database
--- 729,735 ----
/* must unblock signals before calling rebuild_database_list */
PG_SETMASK(&UnBlockSig);
! CoordinatorShmem->co_coordinatorid = MyBackendId;
/*
* Initial population of the database list from pg_database
*************** AutoVacLauncherMain(int argc, char *argv
*** 761,768 ****
if (!PostmasterIsAlive(true))
proc_exit(1);
! can_launch = (AutoVacuumShmem->av_freeWorkers != NULL);
! launcher_determine_sleep(can_launch, false, &nap);
/* Initialize variables for listening on sockets */
FD_ZERO(&socks);
--- 761,768 ----
if (!PostmasterIsAlive(true))
proc_exit(1);
! can_launch = (CoordinatorShmem->co_freeWorkers != NULL);
! coordinator_determine_sleep(can_launch, false, &nap);
/* Initialize variables for listening on sockets */
FD_ZERO(&socks);
*************** AutoVacLauncherMain(int argc, char *argv
*** 847,855 ****
ProcessConfigFile(PGC_SIGHUP);
/* rebalance in case the default cost parameters changed */
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
autovac_balance_cost();
! LWLockRelease(AutovacuumLock);
/* rebuild the list in case the naptime changed */
rebuild_database_list(InvalidOid);
--- 847,855 ----
ProcessConfigFile(PGC_SIGHUP);
/* rebalance in case the default cost parameters changed */
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
autovac_balance_cost();
! LWLockRelease(WorkerInfoLock);
/* rebuild the list in case the naptime changed */
rebuild_database_list(InvalidOid);
*************** AutoVacLauncherMain(int argc, char *argv
*** 885,891 ****
* is currently unable to fork new workers.
*/
pg_usleep(1000000L); /* 1s */
! SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER);
continue;
}
}
--- 885,891 ----
* is currently unable to fork new workers.
*/
pg_usleep(1000000L); /* 1s */
! SendPostmasterSignal(PMSIGNAL_START_BGWORKER);
continue;
}
}
*************** AutoVacLauncherMain(int argc, char *argv
*** 897,906 ****
/* handle pending imessages */
while ((msg = IMessageCheck()) != NULL)
- {
handle_imessage(msg);
- msg = IMessageCheck();
- }
current_time = GetCurrentTimestamp();
can_launch = CoordinatorCanLaunchWorker(current_time);
--- 897,903 ----
*************** AutoVacLauncherMain(int argc, char *argv
*** 915,924 ****
manage_workers(can_launch);
}
! /* Normal exit from the autovac launcher is here */
ereport(LOG,
! (errmsg("autovacuum launcher shutting down")));
! AutoVacuumShmem->av_launcherid = InvalidBackendId;
proc_exit(0); /* done */
}
--- 912,921 ----
manage_workers(can_launch);
}
! /* Normal exit from the coordinator is here */
ereport(LOG,
! (errmsg("coordinator shutting down")));
! CoordinatorShmem->co_coordinatorid = InvalidBackendId;
proc_exit(0); /* done */
}
*************** handle_imessage(IMessage *msg)
*** 991,999 ****
* removed, so there's probably no point in rebalancing here.
* So: FIXME.
*/
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
autovac_balance_cost();
! LWLockRelease(AutovacuumLock);
break;
--- 988,996 ----
* removed, so there's probably no point in rebalancing here.
* So: FIXME.
*/
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
autovac_balance_cost();
! LWLockRelease(WorkerInfoLock);
break;
*************** can_deliver_cached_job(co_database *codb
*** 1067,1073 ****
*
* Starts background workers for databases which have at least one cached
* job or which have less than min_background_workers connected. Within the
! * same loop, the autovacuum_max_workers is checked and terminates a worker
* accordingly.
*
* Note that at max one worker can be requested to start or stop per
--- 1064,1070 ----
*
* Starts background workers for databases which have at least one cached
* job or which have less than min_background_workers connected. Within the
! * same loop, the max_background_workers is checked and terminates a worker
* accordingly.
*
* Note that at max one worker can be requested to start or stop per
*************** manage_workers(bool can_launch)
*** 1085,1093 ****
int idle_workers_required;
int job_workers_required;
! LWLockAcquire(AutovacuumLock, LW_SHARED);
! worker_slots_available = (AutoVacuumShmem->av_freeWorkers != NULL);
! LWLockRelease(AutovacuumLock);
/*
* Terminate an unneeded worker that has been fetched from the list of
--- 1082,1090 ----
int idle_workers_required;
int job_workers_required;
! LWLockAcquire(WorkerInfoLock, LW_SHARED);
! worker_slots_available = (CoordinatorShmem->co_freeWorkers != NULL);
! LWLockRelease(WorkerInfoLock);
/*
* Terminate an unneeded worker that has been fetched from the list of
*************** CoordinatorCanLaunchWorker(TimestampTz c
*** 1213,1226 ****
* other worker failed while starting up.
*/
! LWLockAcquire(AutovacuumLock, LW_SHARED);
! can_launch = (AutoVacuumShmem->av_freeWorkers != NULL);
! if (AutoVacuumShmem->av_startingWorker != NULL)
{
int waittime;
! WorkerInfo worker = AutoVacuumShmem->av_startingWorker;
#ifdef COORDINATOR_DEBUG
elog(DEBUG5, "Coordinator: another worker is starting...");
--- 1210,1223 ----
* other worker failed while starting up.
*/
! LWLockAcquire(WorkerInfoLock, LW_SHARED);
! can_launch = (CoordinatorShmem->co_freeWorkers != NULL);
! if (CoordinatorShmem->co_startingWorker != NULL)
{
int waittime;
! WorkerInfo worker = CoordinatorShmem->co_startingWorker;
#ifdef COORDINATOR_DEBUG
elog(DEBUG5, "Coordinator: another worker is starting...");
*************** CoordinatorCanLaunchWorker(TimestampTz c
*** 1237,1243 ****
* pointer before trying to connect. Problems detected by the
* postmaster (like fork() failure) are also reported and handled
* differently. The only problems that may cause this code to
! * fire are errors in the earlier sections of AutoVacWorkerMain,
* before the worker removes the WorkerInfo from the
* startingWorker pointer.
*/
--- 1234,1240 ----
* pointer before trying to connect. Problems detected by the
* postmaster (like fork() failure) are also reported and handled
* differently. The only problems that may cause this code to
! * fire are errors in the earlier sections of BackgroundWorkerMain,
* before the worker removes the WorkerInfo from the
* startingWorker pointer.
*/
*************** CoordinatorCanLaunchWorker(TimestampTz c
*** 1245,1252 ****
if (TimestampDifferenceExceeds(worker->wi_launchtime, current_time,
waittime))
{
! LWLockRelease(AutovacuumLock);
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
/*
* No other process can put a worker in starting mode, so if
--- 1242,1249 ----
if (TimestampDifferenceExceeds(worker->wi_launchtime, current_time,
waittime))
{
! LWLockRelease(WorkerInfoLock);
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
/*
* No other process can put a worker in starting mode, so if
*************** CoordinatorCanLaunchWorker(TimestampTz c
*** 1254,1276 ****
* we assume it's the same one we saw above (so we don't
* recheck the launch time).
*/
! if (AutoVacuumShmem->av_startingWorker != NULL)
{
! worker = AutoVacuumShmem->av_startingWorker;
worker->wi_dboid = InvalidOid;
worker->wi_tableoid = InvalidOid;
worker->wi_backend_id = InvalidBackendId;
worker->wi_launchtime = 0;
! worker->wi_links.next = (SHM_QUEUE *) AutoVacuumShmem->av_freeWorkers;
! AutoVacuumShmem->av_freeWorkers = worker;
! AutoVacuumShmem->av_startingWorker = NULL;
elog(WARNING, "worker took too long to start; cancelled");
}
}
else
can_launch = false;
}
! LWLockRelease(AutovacuumLock); /* either shared or exclusive */
}
return can_launch;
--- 1251,1273 ----
* we assume it's the same one we saw above (so we don't
* recheck the launch time).
*/
! if (CoordinatorShmem->co_startingWorker != NULL)
{
! worker = CoordinatorShmem->co_startingWorker;
worker->wi_dboid = InvalidOid;
worker->wi_tableoid = InvalidOid;
worker->wi_backend_id = InvalidBackendId;
worker->wi_launchtime = 0;
! worker->wi_links.next = (SHM_QUEUE *) CoordinatorShmem->co_freeWorkers;
! CoordinatorShmem->co_freeWorkers = worker;
! CoordinatorShmem->co_startingWorker = NULL;
elog(WARNING, "worker took too long to start; cancelled");
}
}
else
can_launch = false;
}
! LWLockRelease(WorkerInfoLock); /* either shared or exclusive */
}
return can_launch;
*************** static void
*** 1345,1351 ****
* cause a long sleep, which will be interrupted when a worker exits.
*/
static void
! launcher_determine_sleep(bool can_launch, bool recursing, struct timespec *nap)
{
Dlelem *elem;
--- 1342,1348 ----
* cause a long sleep, which will be interrupted when a worker exits.
*/
static void
! coordinator_determine_sleep(bool can_launch, bool recursing, struct timespec *nap)
{
Dlelem *elem;
*************** launcher_determine_sleep(bool can_launch
*** 1394,1400 ****
if (nap->tv_sec == 0 && nap->tv_nsec == 0 && !recursing)
{
rebuild_database_list(InvalidOid);
! launcher_determine_sleep(can_launch, true, nap);
return;
}
--- 1391,1397 ----
if (nap->tv_sec == 0 && nap->tv_nsec == 0 && !recursing)
{
rebuild_database_list(InvalidOid);
! coordinator_determine_sleep(can_launch, true, nap);
return;
}
*************** rebuild_database_list(Oid newdb)
*** 1435,1441 ****
/* use fresh stats */
autovac_refresh_stats();
! newcxt = AllocSetContextCreate(AutovacLauncherMemCxt,
"AV dblist",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
--- 1432,1438 ----
/* use fresh stats */
autovac_refresh_stats();
! newcxt = AllocSetContextCreate(CoordinatorMemCxt,
"AV dblist",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
*************** rebuild_database_list(Oid newdb)
*** 1576,1582 ****
/*
* Determine the time interval between databases in the schedule. If
* we see that the configured naptime would take us to sleep times
! * lower than our min sleep time (which launcher_determine_sleep is
* coded not to allow), silently use a larger naptime (but don't touch
* the GUC variable).
*/
--- 1573,1579 ----
/*
* Determine the time interval between databases in the schedule. If
* we see that the configured naptime would take us to sleep times
! * lower than our min sleep time (which coordinator_determine_sleep is
* coded not to allow), silently use a larger naptime (but don't touch
* the GUC variable).
*/
*************** db_comparator(const void *a, const void
*** 1626,1632 ****
/*
* do_start_worker
*
! * Bare-bones procedure for starting an autovacuum worker from the
* coordinator. It sets up shared memory stuff and signals the postmaster to
* start a worker.
*/
--- 1623,1629 ----
/*
* do_start_worker
*
! * Bare-bones procedure for starting a background worker from the
* coordinator. It sets up shared memory stuff and signals the postmaster to
* start a worker.
*/
*************** do_start_worker(Oid dboid)
*** 1641,1668 ****
elog(DEBUG3, "Coordinator: requesting worker for database %d.", dboid);
#endif
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
/*
* Get a worker entry from the freelist. We checked above, so there
* really should be a free slot -- complain very loudly if there
* isn't.
*/
! worker = AutoVacuumShmem->av_freeWorkers;
if (worker == NULL)
elog(FATAL, "no free worker found");
! AutoVacuumShmem->av_freeWorkers = (WorkerInfo) worker->wi_links.next;
worker->wi_dboid = dboid;
worker->wi_backend_id = InvalidBackendId;
worker->wi_launchtime = GetCurrentTimestamp();
! AutoVacuumShmem->av_startingWorker = worker;
! LWLockRelease(AutovacuumLock);
! SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER);
}
/*
--- 1638,1665 ----
elog(DEBUG3, "Coordinator: requesting worker for database %d.", dboid);
#endif
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
/*
* Get a worker entry from the freelist. We checked above, so there
* really should be a free slot -- complain very loudly if there
* isn't.
*/
! worker = CoordinatorShmem->co_freeWorkers;
if (worker == NULL)
elog(FATAL, "no free worker found");
! CoordinatorShmem->co_freeWorkers = (WorkerInfo) worker->wi_links.next;
worker->wi_dboid = dboid;
worker->wi_backend_id = InvalidBackendId;
worker->wi_launchtime = GetCurrentTimestamp();
! CoordinatorShmem->co_startingWorker = worker;
! LWLockRelease(WorkerInfoLock);
! SendPostmasterSignal(PMSIGNAL_START_BGWORKER);
}
/*
*************** autovacuum_select_database(void)
*** 1689,1701 ****
oldcxt;
/* return quickly when there are no free workers */
! LWLockAcquire(AutovacuumLock, LW_SHARED);
! if (AutoVacuumShmem->av_freeWorkers == NULL)
{
! LWLockRelease(AutovacuumLock);
return InvalidOid;
}
! LWLockRelease(AutovacuumLock);
/*
* Create and switch to a temporary context to avoid leaking the memory
--- 1686,1698 ----
oldcxt;
/* return quickly when there are no free workers */
! LWLockAcquire(WorkerInfoLock, LW_SHARED);
! if (CoordinatorShmem->co_freeWorkers == NULL)
{
! LWLockRelease(WorkerInfoLock);
return InvalidOid;
}
! LWLockRelease(WorkerInfoLock);
/*
* Create and switch to a temporary context to avoid leaking the memory
*************** avl_sigterm_handler(SIGNAL_ARGS)
*** 1920,1937 ****
#ifdef EXEC_BACKEND
/*
! * forkexec routines for the autovacuum worker.
*
* Format up the arglist, then fork and exec.
*/
static pid_t
! avworker_forkexec(void)
{
char *av[10];
int ac = 0;
av[ac++] = "postgres";
! av[ac++] = "--forkavworker";
av[ac++] = NULL; /* filled in by postmaster_forkexec */
av[ac] = NULL;
--- 1917,1934 ----
#ifdef EXEC_BACKEND
/*
! * forkexec routines for background workers.
*
* Format up the arglist, then fork and exec.
*/
static pid_t
! bgworker_forkexec(void)
{
char *av[10];
int ac = 0;
av[ac++] = "postgres";
! av[ac++] = "--forkbgworker";
av[ac++] = NULL; /* filled in by postmaster_forkexec */
av[ac] = NULL;
*************** void
*** 1944,1974 ****
* We need this set from the outside, before InitProcess is called
*/
void
! AutovacuumWorkerIAm(void)
{
! am_autovacuum_worker = true;
}
#endif
/*
! * Main entry point for autovacuum worker process.
*
* This code is heavily based on pgarch.c, q.v.
*/
int
! StartAutoVacWorker(void)
{
pid_t worker_pid;
#ifdef EXEC_BACKEND
! switch ((worker_pid = avworker_forkexec()))
#else
switch ((worker_pid = fork_process()))
#endif
{
case -1:
ereport(LOG,
! (errmsg("could not fork autovacuum worker process: %m")));
return 0;
#ifndef EXEC_BACKEND
--- 1941,1971 ----
* We need this set from the outside, before InitProcess is called
*/
void
! BackgroundWorkerIAm(void)
{
! am_background_worker = true;
}
#endif
/*
! * Main entry point for a background worker process.
*
* This code is heavily based on pgarch.c, q.v.
*/
int
! StartBackgroundWorker(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 background worker process: %m")));
return 0;
#ifndef EXEC_BACKEND
*************** StartAutoVacWorker(void)
*** 1980,1986 ****
/* Lose the postmaster's on-exit routines */
on_exit_reset();
! AutoVacWorkerMain(0, NULL);
break;
#endif
default:
--- 1977,1983 ----
/* Lose the postmaster's on-exit routines */
on_exit_reset();
! BackgroundWorkerMain(0, NULL);
break;
#endif
default:
*************** StartAutoVacWorker(void)
*** 1995,2001 ****
* add_as_idle_worker
*
* Marks the current worker as idle by adding it to the database's list of
! * idle worker backends. The caller is expected to hold the AutovacuumLock.
*/
static void
add_as_idle_worker(Oid dbid, bool inc_connected_count)
--- 1992,1998 ----
* add_as_idle_worker
*
* Marks the current worker as idle by adding it to the database's list of
! * idle worker backends. The caller is expected to hold the WorkerInfoLock.
*/
static void
add_as_idle_worker(Oid dbid, bool inc_connected_count)
*************** bgworker_job_initialize(worker_state new
*** 2053,2060 ****
* one for other book-keeping of the various background jobs across
* transactions, for example to keep the list of relations to vacuum.
*/
! Assert(AutovacWorkerMemCxt == NULL);
! AutovacWorkerMemCxt = AllocSetContextCreate(TopMemoryContext,
"Background Worker",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
--- 2050,2057 ----
* one for other book-keeping of the various background jobs across
* transactions, for example to keep the list of relations to vacuum.
*/
! Assert(BgWorkerMemCxt == NULL);
! BgWorkerMemCxt = AllocSetContextCreate(TopMemoryContext,
"Background Worker",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
*************** bgworker_job_initialize(worker_state new
*** 2066,2072 ****
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
! MemoryContextSwitchTo(AutovacWorkerMemCxt);
}
/*
--- 2063,2069 ----
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
! MemoryContextSwitchTo(BgWorkerMemCxt);
}
/*
*************** bgworker_reset(void)
*** 2091,2097 ****
void
bgworker_reset(void)
{
! BackendId AutovacuumLauncherId;
IMessage *msg;
elog(DEBUG5, "bg worker [%d/%d]: resetting",
--- 2088,2094 ----
void
bgworker_reset(void)
{
! BackendId CoordinatorId;
IMessage *msg;
elog(DEBUG5, "bg worker [%d/%d]: resetting",
*************** bgworker_reset(void)
*** 2105,2130 ****
set_ps_display("bg worker: idle", false);
/* clean up memory contexts */
! Assert(AutovacWorkerMemCxt);
MemoryContextSwitchTo(TopMemoryContext);
! MemoryContextDelete(AutovacWorkerMemCxt);
! AutovacWorkerMemCxt = NULL;
MemoryContextDelete(MessageContext);
MessageContext = NULL;
! /* Reset the the process-local cleanup handler state. */
BgWorkerCleanupInProgress = false;
/* propagate as idle worker, inform the coordinator */
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
add_as_idle_worker(MyDatabaseId, false);
! LWLockRelease(AutovacuumLock);
! AutovacuumLauncherId = GetAutovacuumLauncherId();
! if (AutovacuumLauncherId != InvalidBackendId)
{
msg = IMessageCreate(IMSGT_READY, 0);
! IMessageActivate(msg, AutovacuumLauncherId);
}
else
elog(WARNING, "bg worker [%d/%d]: no coordinator?!?",
--- 2102,2127 ----
set_ps_display("bg worker: idle", false);
/* clean up memory contexts */
! Assert(BgWorkerMemCxt);
MemoryContextSwitchTo(TopMemoryContext);
! MemoryContextDelete(BgWorkerMemCxt);
! BgWorkerMemCxt = NULL;
MemoryContextDelete(MessageContext);
MessageContext = NULL;
! /* Reset the process-local cleanup handler state. */
BgWorkerCleanupInProgress = false;
/* propagate as idle worker, inform the coordinator */
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
add_as_idle_worker(MyDatabaseId, false);
! LWLockRelease(WorkerInfoLock);
! CoordinatorId = GetCoordinatorId();
! if (CoordinatorId != InvalidBackendId)
{
msg = IMessageCreate(IMSGT_READY, 0);
! IMessageActivate(msg, CoordinatorId);
}
else
elog(WARNING, "bg worker [%d/%d]: no coordinator?!?",
*************** bgworker_job_failed(int errcode)
*** 2164,2173 ****
}
/*
! * AutoVacWorkerMain
*/
NON_EXEC_STATIC void
! AutoVacWorkerMain(int argc, char *argv[])
{
sigjmp_buf local_sigjmp_buf;
BackendId coordinator_id;
--- 2161,2170 ----
}
/*
! * BackgroundWorkerMain
*/
NON_EXEC_STATIC void
! BackgroundWorkerMain(int argc, char *argv[])
{
sigjmp_buf local_sigjmp_buf;
BackendId coordinator_id;
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2178,2184 ****
/* we are a postmaster subprocess now */
IsUnderPostmaster = true;
! am_autovacuum_worker = true;
/* reset MyProcPid */
MyProcPid = getpid();
--- 2175,2181 ----
/* we are a postmaster subprocess now */
IsUnderPostmaster = true;
! am_background_worker = true;
/* reset MyProcPid */
MyProcPid = getpid();
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2187,2193 ****
MyStartTime = time(NULL);
/* Identify myself via ps */
! init_ps_display("autovacuum worker process", "", "", "");
SetProcessingMode(InitProcessing);
--- 2184,2190 ----
MyStartTime = time(NULL);
/* Identify myself via ps */
! init_ps_display("background worker process", "", "", "");
SetProcessingMode(InitProcessing);
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2267,2275 ****
PG_SETMASK(&UnBlockSig);
/*
! * Force zero_damaged_pages OFF in the autovac 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);
--- 2264,2272 ----
PG_SETMASK(&UnBlockSig);
/*
! * Force zero_damaged_pages OFF in the background worker, 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);
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2282,2288 ****
/*
* Get the info about the database we're going to work on.
*/
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
/*
* beware of startingWorker being INVALID; this should normally not
--- 2279,2285 ----
/*
* Get the info about the database we're going to work on.
*/
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
/*
* beware of startingWorker being INVALID; this should normally not
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2290,2304 ****
* launcher might have decided to remove it from the queue and start
* again.
*/
! if (AutoVacuumShmem->av_startingWorker == NULL)
{
/* no worker entry for me, go away */
! elog(WARNING, "autovacuum worker started without a worker entry");
! LWLockRelease(AutovacuumLock);
proc_exit(0);
}
! MyWorkerInfo = AutoVacuumShmem->av_startingWorker;
dbid = MyWorkerInfo->wi_dboid;
/* FIXME: indentation */
--- 2287,2301 ----
* launcher might have decided to remove it from the queue and start
* again.
*/
! if (CoordinatorShmem->co_startingWorker == NULL)
{
/* no worker entry for me, go away */
! elog(WARNING, "background worker started without a worker entry");
! LWLockRelease(WorkerInfoLock);
proc_exit(0);
}
! MyWorkerInfo = CoordinatorShmem->co_startingWorker;
dbid = MyWorkerInfo->wi_dboid;
/* FIXME: indentation */
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2308,2317 ****
* remove from the "starting" pointer, so that the launcher can start
* a new worker if required
*/
! AutoVacuumShmem->av_startingWorker = NULL;
! coordinator_id = AutoVacuumShmem->av_launcherid;
! LWLockRelease(AutovacuumLock);
on_shmem_exit(FreeWorkerInfo, 0);
--- 2305,2314 ----
* remove from the "starting" pointer, so that the launcher can start
* a new worker if required
*/
! CoordinatorShmem->co_startingWorker = NULL;
! coordinator_id = CoordinatorShmem->co_coordinatorid;
! LWLockRelease(WorkerInfoLock);
on_shmem_exit(FreeWorkerInfo, 0);
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2336,2342 ****
set_ps_display("bg worker: idle", false);
}
! AutovacWorkerMemCxt = NULL;
MyWorkerInfo->wi_backend_id = MyBackendId;
MyWorkerInfo->wi_state = WS_IDLE;
--- 2333,2339 ----
set_ps_display("bg worker: idle", false);
}
! BgWorkerMemCxt = NULL;
MyWorkerInfo->wi_backend_id = MyBackendId;
MyWorkerInfo->wi_state = WS_IDLE;
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2351,2359 ****
* set MyProc->databaseId in InitPostgres, so the coordinator can
* determine which database we are connected to.
*/
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
add_as_idle_worker(dbid, true);
! LWLockRelease(AutovacuumLock);
/* register with the coordinator */
if (coordinator_id != InvalidBackendId)
--- 2348,2356 ----
* set MyProc->databaseId in InitPostgres, so the coordinator can
* determine which database we are connected to.
*/
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
add_as_idle_worker(dbid, true);
! LWLockRelease(WorkerInfoLock);
/* register with the coordinator */
if (coordinator_id != InvalidBackendId)
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2414,2423 ****
/*
* Add ourselves to the list of runningWorkers
*/
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
! SHMQueueInsertBefore(&AutoVacuumShmem->av_runningWorkers,
&MyWorkerInfo->wi_links);
! LWLockRelease(AutovacuumLock);
/* do an appropriate amount of work */
do_autovacuum();
--- 2411,2420 ----
/*
* Add ourselves to the list of runningWorkers
*/
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
! SHMQueueInsertBefore(&CoordinatorShmem->co_runningWorkers,
&MyWorkerInfo->wi_links);
! LWLockRelease(WorkerInfoLock);
/* do an appropriate amount of work */
do_autovacuum();
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2426,2434 ****
* Remove ourselves from the list of runningWorkers and
* mark as available background worker.
*/
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
SHMQueueDelete(&MyWorkerInfo->wi_links);
! LWLockRelease(AutovacuumLock);
bgworker_job_completed();
break;
--- 2423,2431 ----
* Remove ourselves from the list of runningWorkers and
* mark as available background worker.
*/
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
SHMQueueDelete(&MyWorkerInfo->wi_links);
! LWLockRelease(WorkerInfoLock);
bgworker_job_completed();
break;
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 2452,2458 ****
ErrorData *errdata;
MemoryContext ecxt;
! ecxt = MemoryContextSwitchTo(AutovacWorkerMemCxt);
errdata = CopyErrorData();
elog(WARNING, "bg worker [%d/%d]: caught error '%s' in %s:%d, state %s",
--- 2449,2455 ----
ErrorData *errdata;
MemoryContext ecxt;
! ecxt = MemoryContextSwitchTo(BgWorkerMemCxt);
errdata = CopyErrorData();
elog(WARNING, "bg worker [%d/%d]: caught error '%s' in %s:%d, state %s",
*************** FreeWorkerInfo(int code, Datum arg)
*** 2505,2516 ****
co_database *codb;
if (MyWorkerInfo != NULL)
{
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
if (!SHMQueueIsDetached(&MyWorkerInfo->wi_links))
SHMQueueDelete(&MyWorkerInfo->wi_links);
! MyWorkerInfo->wi_links.next = (SHM_QUEUE *) AutoVacuumShmem->av_freeWorkers;
MyWorkerInfo->wi_dboid = InvalidOid;
MyWorkerInfo->wi_tableoid = InvalidOid;
MyWorkerInfo->wi_backend_id = InvalidBackendId;
--- 2502,2513 ----
co_database *codb;
if (MyWorkerInfo != NULL)
{
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
if (!SHMQueueIsDetached(&MyWorkerInfo->wi_links))
SHMQueueDelete(&MyWorkerInfo->wi_links);
! MyWorkerInfo->wi_links.next = (SHM_QUEUE *) CoordinatorShmem->co_freeWorkers;
MyWorkerInfo->wi_dboid = InvalidOid;
MyWorkerInfo->wi_tableoid = InvalidOid;
MyWorkerInfo->wi_backend_id = InvalidBackendId;
*************** FreeWorkerInfo(int code, Datum arg)
*** 2518,2524 ****
MyWorkerInfo->wi_cost_delay = 0;
MyWorkerInfo->wi_cost_limit = 0;
MyWorkerInfo->wi_cost_limit_base = 0;
! AutoVacuumShmem->av_freeWorkers = MyWorkerInfo;
/* not mine anymore */
MyWorkerInfo = NULL;
--- 2515,2521 ----
MyWorkerInfo->wi_cost_delay = 0;
MyWorkerInfo->wi_cost_limit = 0;
MyWorkerInfo->wi_cost_limit_base = 0;
! CoordinatorShmem->co_freeWorkers = MyWorkerInfo;
/* not mine anymore */
MyWorkerInfo = NULL;
*************** FreeWorkerInfo(int code, Datum arg)
*** 2529,2535 ****
codb->codb_num_connected_workers--;
LWLockRelease(CoordinatorDatabasesLock);
! LWLockRelease(AutovacuumLock);
}
}
--- 2526,2532 ----
codb->codb_num_connected_workers--;
LWLockRelease(CoordinatorDatabasesLock);
! LWLockRelease(WorkerInfoLock);
}
}
*************** AutoVacuumUpdateDelay(void)
*** 2551,2557 ****
* autovac_balance_cost
* Recalculate the cost limit setting for each active workers.
*
! * Caller must hold the AutovacuumLock in exclusive mode.
*/
static void
autovac_balance_cost(void)
--- 2548,2554 ----
* autovac_balance_cost
* Recalculate the cost limit setting for each active workers.
*
! * Caller must hold the WorkerInfoLock in exclusive mode.
*/
static void
autovac_balance_cost(void)
*************** autovac_balance_cost(void)
*** 2575,2582 ****
/* caculate the total base cost limit of active workers */
cost_total = 0.0;
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
! &AutoVacuumShmem->av_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
--- 2572,2579 ----
/* caculate the total base cost limit of active workers */
cost_total = 0.0;
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
! &CoordinatorShmem->co_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
*************** autovac_balance_cost(void)
*** 2585,2591 ****
cost_total +=
(double) worker->wi_cost_limit_base / worker->wi_cost_delay;
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
--- 2582,2588 ----
cost_total +=
(double) worker->wi_cost_limit_base / worker->wi_cost_delay;
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
*************** autovac_balance_cost(void)
*** 2598,2605 ****
* limit to autovacuum_vacuum_cost_limit.
*/
cost_avail = (double) vac_cost_limit / vac_cost_delay;
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
! &AutoVacuumShmem->av_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
--- 2595,2602 ----
* limit to autovacuum_vacuum_cost_limit.
*/
cost_avail = (double) vac_cost_limit / vac_cost_delay;
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
! &CoordinatorShmem->co_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
*************** autovac_balance_cost(void)
*** 2620,2626 ****
worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_delay);
}
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
--- 2617,2623 ----
worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_delay);
}
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
*************** autovac_balance_cost(void)
*** 2630,2636 ****
* get_database_list
* Return a list of all databases found in pg_database.
*
! * Note: this is the only function in which the autovacuum launcher uses a
* transaction. Although we aren't attached to any particular database and
* therefore can't access most catalogs, we do have enough infrastructure
* to do a seqscan on pg_database.
--- 2627,2633 ----
* get_database_list
* Return a list of all databases found in pg_database.
*
! * Note: this is the only function in which the coordinator uses a
* transaction. Although we aren't attached to any particular database and
* therefore can't access most catalogs, we do have enough infrastructure
* to do a seqscan on pg_database.
*************** get_database_list(void)
*** 2653,2660 ****
StartTransactionCommand();
(void) GetTransactionSnapshot();
! /* Allocate our results in AutovacLauncherMemCxt, not transaction context */
! MemoryContextSwitchTo(AutovacLauncherMemCxt);
rel = heap_open(DatabaseRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
--- 2650,2657 ----
StartTransactionCommand();
(void) GetTransactionSnapshot();
! /* Allocate our results in CoordinatorMemCxt, not transaction context */
! MemoryContextSwitchTo(CoordinatorMemCxt);
rel = heap_open(DatabaseRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
*************** do_autovacuum(void)
*** 2752,2758 ****
NameStr(dbForm->datname))));
/* StartTransactionCommand changed elsewhere */
! MemoryContextSwitchTo(AutovacWorkerMemCxt);
/* The database hash where pgstat keeps shared relations */
shared = pgstat_fetch_stat_dbentry(InvalidOid);
--- 2749,2755 ----
NameStr(dbForm->datname))));
/* StartTransactionCommand changed elsewhere */
! MemoryContextSwitchTo(BgWorkerMemCxt);
/* The database hash where pgstat keeps shared relations */
shared = pgstat_fetch_stat_dbentry(InvalidOid);
*************** do_autovacuum(void)
*** 2966,2972 ****
* create a memory context to act as fake PortalContext, so that the
* contexts created in the vacuum code are cleaned up for each table.
*/
! PortalContext = AllocSetContextCreate(AutovacWorkerMemCxt,
"Autovacuum Portal",
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MINSIZE,
--- 2963,2969 ----
* create a memory context to act as fake PortalContext, so that the
* contexts created in the vacuum code are cleaned up for each table.
*/
! PortalContext = AllocSetContextCreate(BgWorkerMemCxt,
"Autovacuum Portal",
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MINSIZE,
*************** do_autovacuum(void)
*** 2986,3004 ****
/*
* hold schedule lock from here until we're sure that this table still
! * needs vacuuming. We also need the AutovacuumLock to walk the
* worker array, but we'll let go of that one quickly.
*/
! LWLockAcquire(AutovacuumScheduleLock, LW_EXCLUSIVE);
! LWLockAcquire(AutovacuumLock, LW_SHARED);
/*
* Check whether the table is being vacuumed concurrently by another
* worker.
*/
skipit = false;
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
! &AutoVacuumShmem->av_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
--- 2983,3001 ----
/*
* hold schedule lock from here until we're sure that this table still
! * needs vacuuming. We also need the WorkerInfoLock to walk the
* worker array, but we'll let go of that one quickly.
*/
! LWLockAcquire(WorkerScheduleLock, LW_EXCLUSIVE);
! LWLockAcquire(WorkerInfoLock, LW_SHARED);
/*
* Check whether the table is being vacuumed concurrently by another
* worker.
*/
skipit = false;
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
! &CoordinatorShmem->co_runningWorkers,
offsetof(WorkerInfoData, wi_links));
while (worker)
{
*************** do_autovacuum(void)
*** 3017,3030 ****
}
next_worker:
! worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
! LWLockRelease(AutovacuumLock);
if (skipit)
{
! LWLockRelease(AutovacuumScheduleLock);
continue;
}
--- 3014,3027 ----
}
next_worker:
! worker = (WorkerInfo) SHMQueueNext(&CoordinatorShmem->co_runningWorkers,
&worker->wi_links,
offsetof(WorkerInfoData, wi_links));
}
! LWLockRelease(WorkerInfoLock);
if (skipit)
{
! LWLockRelease(WorkerScheduleLock);
continue;
}
*************** do_autovacuum(void)
*** 3038,3049 ****
* that somebody just finished vacuuming this table. The window to
* the race condition is not closed but it is very small.
*/
! MemoryContextSwitchTo(AutovacWorkerMemCxt);
tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
if (tab == NULL)
{
/* someone else vacuumed the table, or it went away */
! LWLockRelease(AutovacuumScheduleLock);
continue;
}
--- 3035,3046 ----
* that somebody just finished vacuuming this table. The window to
* the race condition is not closed but it is very small.
*/
! MemoryContextSwitchTo(BgWorkerMemCxt);
tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
if (tab == NULL)
{
/* someone else vacuumed the table, or it went away */
! LWLockRelease(WorkerScheduleLock);
continue;
}
*************** do_autovacuum(void)
*** 3052,3065 ****
* the lock so that other workers don't vacuum it concurrently.
*/
MyWorkerInfo->wi_tableoid = relid;
! LWLockRelease(AutovacuumScheduleLock);
/* Set the initial vacuum cost parameters for this table */
VacuumCostDelay = tab->at_vacuum_cost_delay;
VacuumCostLimit = tab->at_vacuum_cost_limit;
/* Last fixups before actually starting to work */
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
/* advertise my cost delay parameters for the balancing algorithm */
MyWorkerInfo->wi_cost_delay = tab->at_vacuum_cost_delay;
--- 3049,3062 ----
* the lock so that other workers don't vacuum it concurrently.
*/
MyWorkerInfo->wi_tableoid = relid;
! LWLockRelease(WorkerScheduleLock);
/* Set the initial vacuum cost parameters for this table */
VacuumCostDelay = tab->at_vacuum_cost_delay;
VacuumCostLimit = tab->at_vacuum_cost_limit;
/* Last fixups before actually starting to work */
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
/* advertise my cost delay parameters for the balancing algorithm */
MyWorkerInfo->wi_cost_delay = tab->at_vacuum_cost_delay;
*************** do_autovacuum(void)
*** 3070,3076 ****
autovac_balance_cost();
/* done */
! LWLockRelease(AutovacuumLock);
/* clean up memory before each iteration */
MemoryContextResetAndDeleteChildren(PortalContext);
--- 3067,3073 ----
autovac_balance_cost();
/* done */
! LWLockRelease(WorkerInfoLock);
/* clean up memory before each iteration */
MemoryContextResetAndDeleteChildren(PortalContext);
*************** deleted:
*** 3147,3155 ****
pfree(tab);
/* remove my info from shared memory */
! LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
MyWorkerInfo->wi_tableoid = InvalidOid;
! LWLockRelease(AutovacuumLock);
}
/*
--- 3144,3152 ----
pfree(tab);
/* remove my info from shared memory */
! LWLockAcquire(WorkerInfoLock, LW_EXCLUSIVE);
MyWorkerInfo->wi_tableoid = InvalidOid;
! LWLockRelease(WorkerInfoLock);
}
/*
*************** autovac_init(void)
*** 3579,3622 ****
}
/*
! * IsAutoVacuum functions
! * Return whether this is either a launcher autovacuum process or a worker
! * process.
*/
bool
! IsAutoVacuumLauncherProcess(void)
{
! return am_autovacuum_launcher;
}
bool
! IsAutoVacuumWorkerProcess(void)
{
! return am_autovacuum_worker;
}
/*
! * GetAutovacuumLauncherId
* Returns the backendId of the currently active coordinator process.
*/
BackendId
! GetAutovacuumLauncherId(void)
{
! BackendId AutovacuumLauncherId;
! LWLockAcquire(AutovacuumLock, LW_SHARED);
! AutovacuumLauncherId = AutoVacuumShmem->av_launcherid;
! LWLockRelease(AutovacuumLock);
! return AutovacuumLauncherId;
}
/*
! * AutoVacuumShmemSize
* Compute space needed for autovacuum-related shared memory
*/
Size
! AutoVacuumShmemSize(void)
{
Size size;
--- 3576,3619 ----
}
/*
! * process identification functions
! * Return whether this is either a coordinator process or a background
! * worker process.
*/
bool
! IsCoordinatorProcess(void)
{
! return am_coordinator;
}
bool
! IsBackgroundWorkerProcess(void)
{
! return am_background_worker;
}
/*
! * GetCoordinatorId
* Returns the backendId of the currently active coordinator process.
*/
BackendId
! GetCoordinatorId(void)
{
! BackendId CoordinatorId;
! LWLockAcquire(WorkerInfoLock, LW_SHARED);
! CoordinatorId = CoordinatorShmem->co_coordinatorid;
! LWLockRelease(WorkerInfoLock);
! return CoordinatorId;
}
/*
! * CoordinatorShmemSize
* Compute space needed for autovacuum-related shared memory
*/
Size
! CoordinatorShmemSize(void)
{
Size size;
*************** AutoVacuumShmemSize(void)
*** 3624,3653 ****
* Need the fixed struct and the array of WorkerInfoData, plus per
* database entries in a hash. As we only track databases which have at
* least one worker attached, we won't ever need more than
! * autovacuum_max_workers entries.
*/
! size = sizeof(AutoVacuumShmemStruct);
size = MAXALIGN(size);
! size = add_size(size, mul_size(autovacuum_max_workers,
sizeof(WorkerInfoData)));
! size = add_size(size, hash_estimate_size(autovacuum_max_workers,
sizeof(co_database)));
return size;
}
/*
! * AutoVacuumShmemInit
* Allocate and initialize autovacuum-related shared memory
*/
void
! AutoVacuumShmemInit(void)
{
HASHCTL hctl;
bool found;
! AutoVacuumShmem = (AutoVacuumShmemStruct *)
! ShmemInitStruct("AutoVacuum Data",
! AutoVacuumShmemSize(),
&found);
if (!IsUnderPostmaster)
--- 3621,3650 ----
* Need the fixed struct and the array of WorkerInfoData, plus per
* database entries in a hash. As we only track databases which have at
* least one worker attached, we won't ever need more than
! * max_background_workers entries.
*/
! size = sizeof(CoordinatorShmemStruct);
size = MAXALIGN(size);
! size = add_size(size, mul_size(max_background_workers,
sizeof(WorkerInfoData)));
! size = add_size(size, hash_estimate_size(max_background_workers,
sizeof(co_database)));
return size;
}
/*
! * CoordinatorShmemInit
* Allocate and initialize autovacuum-related shared memory
*/
void
! CoordinatorShmemInit(void)
{
HASHCTL hctl;
bool found;
! CoordinatorShmem = (CoordinatorShmemStruct *)
! ShmemInitStruct("Background Worker Data",
! CoordinatorShmemSize(),
&found);
if (!IsUnderPostmaster)
*************** AutoVacuumShmemInit(void)
*** 3657,3675 ****
Assert(!found);
! AutoVacuumShmem->av_launcherid = InvalidBackendId;
! AutoVacuumShmem->av_freeWorkers = NULL;
! SHMQueueInit(&AutoVacuumShmem->av_runningWorkers);
! AutoVacuumShmem->av_startingWorker = NULL;
! worker = (WorkerInfo) ((char *) AutoVacuumShmem +
! MAXALIGN(sizeof(AutoVacuumShmemStruct)));
/* initialize the WorkerInfo free list */
! for (i = 0; i < autovacuum_max_workers; i++)
{
! worker[i].wi_links.next = (SHM_QUEUE *) AutoVacuumShmem->av_freeWorkers;
! AutoVacuumShmem->av_freeWorkers = &worker[i];
}
}
else
--- 3654,3672 ----
Assert(!found);
! CoordinatorShmem->co_coordinatorid = InvalidBackendId;
! CoordinatorShmem->co_freeWorkers = NULL;
! SHMQueueInit(&CoordinatorShmem->co_runningWorkers);
! CoordinatorShmem->co_startingWorker = NULL;
! worker = (WorkerInfo) ((char *) CoordinatorShmem +
! MAXALIGN(sizeof(CoordinatorShmemStruct)));
/* initialize the WorkerInfo free list */
! for (i = 0; i < max_background_workers; i++)
{
! worker[i].wi_links.next = (SHM_QUEUE *) CoordinatorShmem->co_freeWorkers;
! CoordinatorShmem->co_freeWorkers = &worker[i];
}
}
else
*************** AutoVacuumShmemInit(void)
*** 3679,3686 ****
hctl.entrysize = sizeof(co_database);
hctl.hash = oid_hash;
co_databases = ShmemInitHash("Coordinator Database Info",
! autovacuum_max_workers,
! autovacuum_max_workers,
&hctl,
HASH_ELEM | HASH_FUNCTION);
}
--- 3676,3683 ----
hctl.entrysize = sizeof(co_database);
hctl.hash = oid_hash;
co_databases = ShmemInitHash("Coordinator Database Info",
! max_background_workers,
! max_background_workers,
&hctl,
HASH_ELEM | HASH_FUNCTION);
}
*************** AutoVacuumShmemInit(void)
*** 3690,3698 ****
* Refresh pgstats data for an autovacuum process
*
* Cause the next pgstats read operation to obtain fresh data, but throttle
! * such refreshing in the autovacuum launcher. This is mostly to avoid
! * rereading the pgstats files too many times in quick succession when there
! * are many databases.
*
* Note: we avoid throttling in the autovac worker, as it would be
* counterproductive in the recheck logic.
--- 3687,3695 ----
* Refresh pgstats data for an autovacuum process
*
* Cause the next pgstats read operation to obtain fresh data, but throttle
! * such refreshing in the coordinator. This is mostly to avoid rereading
! * the pgstats files too many times in quick succession when there are many
! * databases.
*
* Note: we avoid throttling in the autovac worker, as it would be
* counterproductive in the recheck logic.
*************** autovac_refresh_stats(void)
*** 3700,3706 ****
static void
autovac_refresh_stats(void)
{
! if (IsAutoVacuumLauncherProcess())
{
static TimestampTz last_read = 0;
TimestampTz current_time;
--- 3697,3703 ----
static void
autovac_refresh_stats(void)
{
! if (IsCoordinatorProcess())
{
static TimestampTz last_read = 0;
TimestampTz current_time;
============================================================
*** src/include/postmaster/autovacuum.h 0937b36c82e931677a8fed1cdd638f0138155086
--- src/include/postmaster/autovacuum.h dc90d7a23ab19ae8e9f5fb9815469058bce97f31
*************** typedef enum
*** 31,44 ****
} worker_state;
! #define IsIdleWorker(wi) (IsAutoVacuumWorkerProcess() && (wi->wi_state == WS_IDLE))
! #define IsAutoVacuumWorker(wi) (IsAutoVacuumWorkerProcess() && (wi->wi_state == WS_AUTOVACUUM))
/*-------------
* This struct holds information about a single worker's whereabouts. We keep
* an array of these in shared memory, sized according to
! * autovacuum_max_workers.
*
* wi_links entry into free list or running list
* wi_dboid OID of the database this worker is supposed to work on
--- 31,44 ----
} worker_state;
! #define IsIdleWorker(wi) (IsBackgroundWorkerProcess() && (wi->wi_state == WS_IDLE))
! #define IsAutoVacuumWorker(wi) (IsBackgroundWorkerProcess() && (wi->wi_state == WS_AUTOVACUUM))
/*-------------
* This struct holds information about a single worker's whereabouts. We keep
* an array of these in shared memory, sized according to
! * max_background_workers.
*
* wi_links entry into free list or running list
* wi_dboid OID of the database this worker is supposed to work on
*************** typedef enum
*** 48,55 ****
* wi_tableoid OID of the table currently being vacuumed
* wi_cost_* Vacuum cost-based delay parameters current in this worker
*
! * All fields are protected by AutovacuumLock, except for wi_tableoid which is
! * protected by AutovacuumScheduleLock (which is read-only for everyone except
* that worker itself).
*-------------
*/
--- 48,55 ----
* wi_tableoid OID of the table currently being vacuumed
* wi_cost_* Vacuum cost-based delay parameters current in this worker
*
! * All fields are protected by WorkerInfoLock, except for wi_tableoid which is
! * protected by WorkerScheduleLock (which is read-only for everyone except
* that worker itself).
*-------------
*/
*************** extern bool autovacuum_enabled;
*** 88,94 ****
/* GUC variables */
extern bool autovacuum_enabled;
! extern int autovacuum_max_workers;
extern int min_spare_background_workers;
extern int max_spare_background_workers;
extern int autovacuum_naptime;
--- 88,94 ----
/* GUC variables */
extern bool autovacuum_enabled;
! extern int max_background_workers;
extern int min_spare_background_workers;
extern int max_spare_background_workers;
extern int autovacuum_naptime;
*************** extern char *decode_worker_state(worker_
*** 105,132 ****
extern char *decode_worker_state(worker_state state);
/* Status inquiry functions */
! extern bool IsAutoVacuumLauncherProcess(void);
! extern bool IsAutoVacuumWorkerProcess(void);
! extern BackendId GetAutovacuumLauncherId(void);
/* Functions to start autovacuum process, called from postmaster */
extern void autovac_init(void);
! extern int StartAutoVacLauncher(void);
! extern int StartAutoVacWorker(void);
/* autovacuum cost-delay balancer */
extern void AutoVacuumUpdateDelay(void);
#ifdef EXEC_BACKEND
! extern void AutoVacLauncherMain(int argc, char *argv[]);
! extern void AutoVacWorkerMain(int argc, char *argv[]);
! extern void AutovacuumWorkerIAm(void);
! extern void AutovacuumLauncherIAm(void);
#endif
/* shared memory stuff */
! extern Size AutoVacuumShmemSize(void);
! extern void AutoVacuumShmemInit(void);
/* bgworker job management functions */
extern void bgworker_job_failed(int errcode);
--- 105,132 ----
extern char *decode_worker_state(worker_state state);
/* Status inquiry functions */
! extern bool IsCoordinatorProcess(void);
! extern bool IsBackgroundWorkerProcess(void);
! extern BackendId GetCoordinatorId(void);
/* Functions to start autovacuum process, called from postmaster */
extern void autovac_init(void);
! extern int StartCoordinator(void);
! extern int StartBackgroundWorker(void);
/* autovacuum cost-delay balancer */
extern void AutoVacuumUpdateDelay(void);
#ifdef EXEC_BACKEND
! extern void CoordinatorMain(int argc, char *argv[]);
! extern void BackgroundWorkerMain(int argc, char *argv[]);
! extern void BackgroundWorkerIAm(void);
! extern void CoordinatorIAm(void);
#endif
/* shared memory stuff */
! extern Size CoordinatorShmemSize(void);
! extern void CoordinatorShmemInit(void);
/* bgworker job management functions */
extern void bgworker_job_failed(int errcode);
============================================================
*** src/backend/access/gin/ginvacuum.c 26dc9ae0821cbed10085e6e6b7a0de4d8dd55192
--- src/backend/access/gin/ginvacuum.c a5ee1da6e8a01eaa4e7df35f77e1b3696de99f4b
*************** ginvacuumcleanup(PG_FUNCTION_ARGS)
*** 717,723 ****
*/
if (info->analyze_only)
{
! if (IsAutoVacuumWorkerProcess())
{
initGinState(&ginstate, index);
ginInsertCleanup(index, &ginstate, true, stats);
--- 717,723 ----
*/
if (info->analyze_only)
{
! if (IsBackgroundWorkerProcess())
{
initGinState(&ginstate, index);
ginInsertCleanup(index, &ginstate, true, stats);