From: Tom Lane Date: Mon, 31 Aug 2009 19:41:00 +0000 (+0000) Subject: Change the autovacuum launcher to read pg_database directly, rather than X-Git-Tag: REL8_5_ALPHA2~144 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00e6a16d01683762c2f34eb4909fc739093ab3bf;p=postgresql Change the autovacuum launcher to read pg_database directly, rather than via the "flat files" facility. This requires making it enough like a backend to be able to run transactions; it's no longer an "auxiliary process" but more like the autovacuum worker processes. Also, its signal handling has to be brought into line with backends/workers. In particular, since it now has to handle procsignal.c processing, the special autovac-launcher-only signal conditions are moved to SIGUSR2. Alvaro, with some cleanup from Tom --- diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index ea4fe65b51..41bd37d72a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -35,7 +35,7 @@ * worker and dealt with just by having the worker exit normally. The launcher * will launch a new worker again later, per schedule. * - * When the worker is done vacuuming it sends SIGUSR1 to the launcher. The + * When the worker is done vacuuming it sends SIGUSR2 to the launcher. The * launcher then wakes up and is able to launch another worker, if the schedule * is so tight that a new worker is needed immediately. At this time the * launcher can also balance the settings for the various remaining workers' @@ -55,7 +55,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.103 2009/08/27 17:18:44 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.104 2009/08/31 19:40:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -67,18 +67,15 @@ #include #include -#include "access/genam.h" #include "access/heapam.h" #include "access/reloptions.h" #include "access/transam.h" #include "access/xact.h" #include "catalog/dependency.h" -#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_database.h" #include "commands/dbcommands.h" #include "commands/vacuum.h" -#include "libpq/hba.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" @@ -86,20 +83,17 @@ #include "postmaster/fork_process.h" #include "postmaster/postmaster.h" #include "storage/bufmgr.h" -#include "storage/fd.h" #include "storage/ipc.h" #include "storage/pmsignal.h" #include "storage/proc.h" -#include "storage/procarray.h" #include "storage/procsignal.h" #include "storage/sinvaladt.h" #include "tcop/tcopprot.h" -#include "utils/dynahash.h" -#include "utils/flatfiles.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/ps_status.h" +#include "utils/snapmgr.h" #include "utils/syscache.h" #include "utils/tqual.h" @@ -133,7 +127,7 @@ static bool am_autovacuum_worker = false; /* Flags set by signal handlers */ static volatile sig_atomic_t got_SIGHUP = false; -static volatile sig_atomic_t got_SIGUSR1 = false; +static volatile sig_atomic_t got_SIGUSR2 = false; static volatile sig_atomic_t got_SIGTERM = false; /* Comparison point for determining whether freeze_max_age is exceeded */ @@ -303,9 +297,8 @@ static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *dbentry); static void autovac_report_activity(autovac_table *tab); static void avl_sighup_handler(SIGNAL_ARGS); -static void avl_sigusr1_handler(SIGNAL_ARGS); +static void avl_sigusr2_handler(SIGNAL_ARGS); static void avl_sigterm_handler(SIGNAL_ARGS); -static void avl_quickdie(SIGNAL_ARGS); static void autovac_refresh_stats(void); @@ -407,6 +400,9 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Identify myself via ps */ init_ps_display("autovacuum launcher process", "", "", ""); + ereport(LOG, + (errmsg("autovacuum launcher started"))); + if (PostAuthDelay) pg_usleep(PostAuthDelay * 1000000L); @@ -424,20 +420,20 @@ AutoVacLauncherMain(int argc, char *argv[]) #endif /* - * Set up signal handlers. Since this is an auxiliary process, it has - * particular signal requirements -- no deadlock checker or sinval - * catchup, for example. + * Set up signal handlers. We operate on databases much like a regular + * backend, so we use the same signal handling. See equivalent code in + * tcop/postgres.c. */ pqsignal(SIGHUP, avl_sighup_handler); - - pqsignal(SIGINT, SIG_IGN); + pqsignal(SIGINT, StatementCancelHandler); pqsignal(SIGTERM, avl_sigterm_handler); - pqsignal(SIGQUIT, avl_quickdie); - pqsignal(SIGALRM, SIG_IGN); + + pqsignal(SIGQUIT, quickdie); + pqsignal(SIGALRM, handle_sig_alarm); pqsignal(SIGPIPE, SIG_IGN); - pqsignal(SIGUSR1, avl_sigusr1_handler); - pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGUSR1, procsignal_sigusr1_handler); + pqsignal(SIGUSR2, avl_sigusr2_handler); pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGCHLD, SIG_DFL); @@ -451,9 +447,13 @@ AutoVacLauncherMain(int argc, char *argv[]) * had to do some stuff with LWLocks). */ #ifndef EXEC_BACKEND - InitAuxiliaryProcess(); + InitProcess(); #endif + InitPostgres(NULL, InvalidOid, NULL, NULL); + + SetProcessingMode(NormalProcessing); + /* * Create a memory context that we will do all our work in. We do this so * that we can reset the context during error recovery and thereby avoid @@ -466,11 +466,10 @@ AutoVacLauncherMain(int argc, char *argv[]) ALLOCSET_DEFAULT_MAXSIZE); MemoryContextSwitchTo(AutovacMemCxt); - /* * If an exception is encountered, processing resumes here. * - * This code is heavily based on bgwriter.c, q.v. + * This code is a stripped down version of PostgresMain error recovery. */ if (sigsetjmp(local_sigjmp_buf, 1) != 0) { @@ -480,17 +479,16 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Prevents interrupts while cleaning up */ HOLD_INTERRUPTS(); + /* Forget any pending QueryCancel request */ + QueryCancelPending = false; + disable_sig_alarm(true); + QueryCancelPending = false; /* again in case timeout occurred */ + /* Report the error to the server log */ EmitErrorReport(); - /* - * These operations are really just a minimal subset of - * AbortTransaction(). We don't have very many resources to worry - * about, but we do have LWLocks. - */ - LWLockReleaseAll(); - AtEOXact_Files(); - AtEOXact_HashTables(false); + /* Abort the current transaction in order to recover */ + AbortCurrentTransaction(); /* * Now return to normal top-level context and clear ErrorContext for @@ -525,9 +523,6 @@ AutoVacLauncherMain(int argc, char *argv[]) /* We can now handle ereport(ERROR) */ PG_exception_stack = &local_sigjmp_buf; - ereport(LOG, - (errmsg("autovacuum launcher started"))); - /* must unblock signals before calling rebuild_database_list */ PG_SETMASK(&UnBlockSig); @@ -561,11 +556,14 @@ AutoVacLauncherMain(int argc, char *argv[]) * necessity for manual cleanup of all postmaster children. */ if (!PostmasterIsAlive(true)) - exit(1); + proc_exit(1); launcher_determine_sleep((AutoVacuumShmem->av_freeWorkers != NULL), false, &nap); + /* Allow sinval catchup interrupts while sleeping */ + EnableCatchupInterrupt(); + /* * Sleep for a while according to schedule. * @@ -595,12 +593,14 @@ AutoVacLauncherMain(int argc, char *argv[]) * necessity for manual cleanup of all postmaster children. */ if (!PostmasterIsAlive(true)) - exit(1); + proc_exit(1); - if (got_SIGTERM || got_SIGHUP || got_SIGUSR1) + if (got_SIGTERM || got_SIGHUP || got_SIGUSR2) break; } + DisableCatchupInterrupt(); + /* the normal shutdown case */ if (got_SIGTERM) break; @@ -610,7 +610,7 @@ AutoVacLauncherMain(int argc, char *argv[]) got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); - /* shutdown requested in config file */ + /* shutdown requested in config file? */ if (!AutoVacuumingActive()) break; @@ -627,9 +627,9 @@ AutoVacLauncherMain(int argc, char *argv[]) * a worker finished, or postmaster signalled failure to start a * worker */ - if (got_SIGUSR1) + if (got_SIGUSR2) { - got_SIGUSR1 = false; + got_SIGUSR2 = false; /* rebalance cost limits, if needed */ if (AutoVacuumShmem->av_signal[AutoVacRebalance]) @@ -1306,7 +1306,7 @@ launch_worker(TimestampTz now) /* * Called from postmaster to signal a failure to fork a process to become - * worker. The postmaster should kill(SIGUSR1) the launcher shortly + * worker. The postmaster should kill(SIGUSR2) the launcher shortly * after calling this function. */ void @@ -1322,11 +1322,11 @@ avl_sighup_handler(SIGNAL_ARGS) got_SIGHUP = true; } -/* SIGUSR1: a worker is up and running, or just finished, or failed to fork */ +/* SIGUSR2: a worker is up and running, or just finished, or failed to fork */ static void -avl_sigusr1_handler(SIGNAL_ARGS) +avl_sigusr2_handler(SIGNAL_ARGS) { - got_SIGUSR1 = true; + got_SIGUSR2 = true; } /* SIGTERM: time to die */ @@ -1336,38 +1336,6 @@ avl_sigterm_handler(SIGNAL_ARGS) got_SIGTERM = true; } -/* - * avl_quickdie occurs when signalled SIGQUIT from postmaster. - * - * Some backend has bought the farm, so we need to stop what we're doing - * and exit. - */ -static void -avl_quickdie(SIGNAL_ARGS) -{ - PG_SETMASK(&BlockSig); - - /* - * We DO NOT want to run proc_exit() callbacks -- we're here because - * shared memory may be corrupted, so we don't want to try to clean up our - * transaction. Just nail the windows shut and get out of town. Now that - * there's an atexit callback to prevent third-party code from breaking - * things by calling exit() directly, we have to reset the callbacks - * explicitly to make this work as intended. - */ - on_exit_reset(); - - /* - * Note we do exit(2) not exit(0). This is to force the postmaster into a - * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - exit(2); -} - /******************************************************************** * AUTOVACUUM WORKER CODE @@ -1590,7 +1558,7 @@ AutoVacWorkerMain(int argc, char *argv[]) /* wake up the launcher */ if (AutoVacuumShmem->av_launcherpid != 0) - kill(AutoVacuumShmem->av_launcherpid, SIGUSR1); + kill(AutoVacuumShmem->av_launcherpid, SIGUSR2); } else { @@ -1784,46 +1752,57 @@ autovac_balance_cost(void) /* * get_database_list + * Return a list of all databases found in pg_database. * - * Return a list of all databases. Note we cannot use pg_database, - * because we aren't connected; we use the flat database file. + * 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. */ static List * get_database_list(void) { - char *filename; List *dblist = NIL; - char thisname[NAMEDATALEN]; - FILE *db_file; - Oid db_id; - Oid db_tablespace; - TransactionId db_frozenxid; - - filename = database_getflatfilename(); - db_file = AllocateFile(filename, "r"); - if (db_file == NULL) - ereport(FATAL, - (errcode_for_file_access(), - errmsg("could not open file \"%s\": %m", filename))); + Relation rel; + HeapScanDesc scan; + HeapTuple tup; + + /* + * Start a transaction so we can access pg_database, and get a snapshot. + * We don't have a use for the snapshot itself, but we're interested in + * the secondary effect that it sets RecentGlobalXmin. (This is critical + * for anything that reads heap pages, because HOT may decide to prune + * them even if the process doesn't attempt to modify any tuples.) + */ + StartTransactionCommand(); + (void) GetTransactionSnapshot(); + + /* Allocate our results in AutovacMemCxt, not transaction context */ + MemoryContextSwitchTo(AutovacMemCxt); - while (read_pg_database_line(db_file, thisname, &db_id, - &db_tablespace, &db_frozenxid)) + rel = heap_open(DatabaseRelationId, AccessShareLock); + scan = heap_beginscan(rel, SnapshotNow, 0, NULL); + + while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) { - avw_dbase *avdb; + Form_pg_database pgdatabase = (Form_pg_database) GETSTRUCT(tup); + avw_dbase *avdb; avdb = (avw_dbase *) palloc(sizeof(avw_dbase)); - avdb->adw_datid = db_id; - avdb->adw_name = pstrdup(thisname); - avdb->adw_frozenxid = db_frozenxid; + avdb->adw_datid = HeapTupleGetOid(tup); + avdb->adw_name = pstrdup(NameStr(pgdatabase->datname)); + avdb->adw_frozenxid = pgdatabase->datfrozenxid; /* this gets set later: */ avdb->adw_entry = NULL; dblist = lappend(dblist, avdb); } - FreeFile(db_file); - pfree(filename); + heap_endscan(scan); + heap_close(rel, AccessShareLock); + + CommitTransactionCommand(); return dblist; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 3f77333641..c4d8d8ae8d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.593 2009/08/29 19:26:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.594 2009/08/31 19:41:00 tgl Exp $ * * NOTES * @@ -1442,7 +1442,7 @@ ServerLoop(void) { avlauncher_needs_signal = false; if (AutoVacPID != 0) - kill(AutoVacPID, SIGUSR1); + kill(AutoVacPID, SIGUSR2); } /* @@ -3865,7 +3865,7 @@ SubPostmasterMain(int argc, char *argv[]) InitShmemAccess(UsedShmemSegAddr); /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ - InitAuxiliaryProcess(); + InitProcess(); /* Attach process to shared data structures */ CreateSharedMemoryAndSemaphores(false, 0); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index d9a0a689f8..56a785d138 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.208 2009/08/12 20:53:30 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.209 2009/08/31 19:41:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -102,7 +102,7 @@ ProcGlobalShmemSize(void) size = add_size(size, sizeof(PROC_HDR)); /* AuxiliaryProcs */ size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC))); - /* MyProcs, including autovacuum */ + /* MyProcs, including autovacuum workers and launcher */ size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC))); /* ProcStructLock */ size = add_size(size, sizeof(slock_t)); @@ -192,19 +192,27 @@ InitProcGlobal(void) ProcGlobal->freeProcs = &procs[i]; } - procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers) * sizeof(PGPROC)); + /* + * Likewise for the PGPROCs reserved for autovacuum. + * + * 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 * sizeof(PGPROC)); - for (i = 0; i < autovacuum_max_workers; i++) + 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; ProcGlobal->autovacFreeProcs = &procs[i]; } + /* + * And auxiliary procs. + */ MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC)); for (i = 0; i < NUM_AUXILIARY_PROCS; i++) { @@ -248,14 +256,14 @@ InitProcess(void) set_spins_per_delay(procglobal->spins_per_delay); - if (IsAutoVacuumWorkerProcess()) + if (IsAnyAutoVacuumProcess()) MyProc = procglobal->autovacFreeProcs; else MyProc = procglobal->freeProcs; if (MyProc != NULL) { - if (IsAutoVacuumWorkerProcess()) + if (IsAnyAutoVacuumProcess()) procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next; else procglobal->freeProcs = (PGPROC *) MyProc->links.next; @@ -278,9 +286,10 @@ InitProcess(void) /* * Now that we have a PGPROC, mark ourselves as an active postmaster * child; this is so that the postmaster can detect it if we exit without - * cleaning up. + * cleaning up. (XXX autovac launcher currently doesn't participate in + * this; it probably should.) */ - if (IsUnderPostmaster) + if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess()) MarkPostmasterChildActive(); /* @@ -299,6 +308,7 @@ InitProcess(void) MyProc->roleId = InvalidOid; 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; @@ -429,7 +439,6 @@ InitAuxiliaryProcess(void) MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->inCommit = false; - /* we don't set the "is autovacuum" flag in the launcher */ MyProc->vacuumFlags = 0; MyProc->lwWaiting = false; MyProc->lwExclusive = false; @@ -595,8 +604,8 @@ ProcKill(int code, Datum arg) SpinLockAcquire(ProcStructLock); - /* Return PGPROC structure (and semaphore) to freelist */ - if (IsAutoVacuumWorkerProcess()) + /* Return PGPROC structure (and semaphore) to appropriate freelist */ + if (IsAnyAutoVacuumProcess()) { MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs; procglobal->autovacFreeProcs = MyProc; @@ -618,13 +627,14 @@ ProcKill(int code, Datum arg) /* * This process is no longer present in shared memory in any meaningful * way, so tell the postmaster we've cleaned up acceptably well. + * (XXX autovac launcher should be included here someday) */ - if (IsUnderPostmaster) + if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess()) MarkPostmasterChildInactive(); /* wake autovac launcher if needed -- see comments in FreeWorkerInfo */ if (AutovacuumLauncherPid != 0) - kill(AutovacuumLauncherPid, SIGUSR1); + kill(AutovacuumLauncherPid, SIGUSR2); } /* diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index e4f5dfa584..fe2cef87d3 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.109 2009/08/28 18:23:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.110 2009/08/31 19:41:00 tgl Exp $ * * NOTES * Globals used all over the place should be declared here and not @@ -100,8 +100,8 @@ int maintenance_work_mem = 16384; /* * Primary determinants of sizes of shared-memory structures. MaxBackends is - * MaxConnections + autovacuum_max_workers (it is computed by the GUC assign - * hook): + * MaxConnections + autovacuum_max_workers + 1 (it is computed by the GUC + * assign hooks for those variables): */ int NBuffers = 1000; int MaxBackends = 100; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 11eeec353c..2d7253312f 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.195 2009/08/29 19:26:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.196 2009/08/31 19:41:00 tgl Exp $ * * *------------------------------------------------------------------------- @@ -460,7 +460,9 @@ BaseInit(void) * name can be returned to the caller in out_dbname. If out_dbname isn't * NULL, it must point to a buffer of size NAMEDATALEN. * - * In bootstrap mode no parameters are used. + * In bootstrap mode no parameters are used. The autovacuum launcher process + * doesn't use any parameters either, because it only goes far enough to be + * able to read pg_database; it doesn't connect to any particular database. * * The return value indicates whether the userID is a superuser. (That * can only be tested inside a transaction, so we want to do it during @@ -537,6 +539,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, if (!bootstrap) pgstat_initialize(); + /* + * Load relcache entries for the shared system catalogs. This must + * create at least an entry for pg_database. + */ + RelationCacheInitializePhase2(); + /* * Set up process-exit callback to do pre-shutdown cleanup. This has to * be after we've initialized all the low-level modules like the buffer @@ -548,10 +556,17 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, */ on_shmem_exit(ShutdownPostgres, 0); + /* The autovacuum launcher is done here */ + if (IsAutoVacuumLauncherProcess()) + return true; /* result doesn't matter */ + /* * Start a new transaction here before first access to db, and get a * snapshot. We don't have a use for the snapshot itself, but we're * interested in the secondary effect that it sets RecentGlobalXmin. + * (This is critical for anything that reads heap pages, because HOT + * may decide to prune them even if the process doesn't attempt to + * modify any tuples.) */ if (!bootstrap) { @@ -559,12 +574,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, (void) GetTransactionSnapshot(); } - /* - * Load relcache entries for the shared system catalogs. This must - * create at least an entry for pg_database. - */ - RelationCacheInitializePhase2(); - /* * Set up the global variables holding database id and default tablespace. * But note we won't actually try to touch the database just yet. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 66904e6b09..03e2408737 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.513 2009/08/31 02:23:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.514 2009/08/31 19:41:00 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -1335,7 +1335,7 @@ static struct config_int ConfigureNamesInt[] = * 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 autovacuum_max_workers plus one (for the autovacuum launcher). * * Likewise we have to limit NBuffers to INT_MAX/2. */ @@ -7570,11 +7570,11 @@ show_tcp_keepalives_count(void) static bool assign_maxconnections(int newval, bool doit, GucSource source) { - if (newval + autovacuum_max_workers > INT_MAX / 4) + if (newval + autovacuum_max_workers + 1 > INT_MAX / 4) return false; if (doit) - MaxBackends = newval + autovacuum_max_workers; + MaxBackends = newval + autovacuum_max_workers + 1; return true; } @@ -7582,11 +7582,11 @@ assign_maxconnections(int newval, bool doit, GucSource source) static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source) { - if (newval + MaxConnections > INT_MAX / 4) + if (MaxConnections + newval + 1 > INT_MAX / 4) return false; if (doit) - MaxBackends = newval + MaxConnections; + MaxBackends = MaxConnections + newval + 1; return true; } diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index 3175487af3..dcdf57cdd4 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.15 2009/01/01 17:24:01 momjian Exp $ + * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.16 2009/08/31 19:41:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,8 @@ extern int Log_autovacuum_min_duration; extern bool AutoVacuumingActive(void); extern bool IsAutoVacuumLauncherProcess(void); extern bool IsAutoVacuumWorkerProcess(void); +#define IsAnyAutoVacuumProcess() \ + (IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess()) /* Functions to start autovacuum process, called from postmaster */ extern void autovac_init(void); diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 98bb41103d..c8a9042fdc 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.113 2009/08/12 20:53:30 tgl Exp $ + * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.114 2009/08/31 19:41:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -141,12 +141,11 @@ typedef struct PROC_HDR * We set aside some extra PGPROC structures for auxiliary processes, * ie things that aren't full-fledged backends but need shmem access. * - * Background writer, WAL writer, and autovacuum launcher run during - * normal operation. Startup process also consumes one slot, but WAL - * writer and autovacuum launcher are launched only after it has - * exited. + * Background writer and WAL writer run during normal operation. Startup + * process also consumes one slot, but WAL writer is launched only after + * startup has exited, so we only need 2 slots. */ -#define NUM_AUXILIARY_PROCS 3 +#define NUM_AUXILIARY_PROCS 2 /* configurable options */