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
This commit is contained in:
parent
25ec228ef7
commit
00e6a16d01
@ -35,7 +35,7 @@
|
|||||||
* worker and dealt with just by having the worker exit normally. The launcher
|
* worker and dealt with just by having the worker exit normally. The launcher
|
||||||
* will launch a new worker again later, per schedule.
|
* 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
|
* 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
|
* 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'
|
* launcher can also balance the settings for the various remaining workers'
|
||||||
@ -55,7 +55,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "access/genam.h"
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/reloptions.h"
|
#include "access/reloptions.h"
|
||||||
#include "access/transam.h"
|
#include "access/transam.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "catalog/dependency.h"
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/indexing.h"
|
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_database.h"
|
#include "catalog/pg_database.h"
|
||||||
#include "commands/dbcommands.h"
|
#include "commands/dbcommands.h"
|
||||||
#include "commands/vacuum.h"
|
#include "commands/vacuum.h"
|
||||||
#include "libpq/hba.h"
|
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
@ -86,20 +83,17 @@
|
|||||||
#include "postmaster/fork_process.h"
|
#include "postmaster/fork_process.h"
|
||||||
#include "postmaster/postmaster.h"
|
#include "postmaster/postmaster.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
#include "storage/fd.h"
|
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
#include "storage/pmsignal.h"
|
#include "storage/pmsignal.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
#include "storage/procarray.h"
|
|
||||||
#include "storage/procsignal.h"
|
#include "storage/procsignal.h"
|
||||||
#include "storage/sinvaladt.h"
|
#include "storage/sinvaladt.h"
|
||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/dynahash.h"
|
|
||||||
#include "utils/flatfiles.h"
|
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/ps_status.h"
|
#include "utils/ps_status.h"
|
||||||
|
#include "utils/snapmgr.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/tqual.h"
|
#include "utils/tqual.h"
|
||||||
|
|
||||||
@ -133,7 +127,7 @@ static bool am_autovacuum_worker = false;
|
|||||||
|
|
||||||
/* Flags set by signal handlers */
|
/* Flags set by signal handlers */
|
||||||
static volatile sig_atomic_t got_SIGHUP = false;
|
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;
|
static volatile sig_atomic_t got_SIGTERM = false;
|
||||||
|
|
||||||
/* Comparison point for determining whether freeze_max_age is exceeded */
|
/* 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);
|
PgStat_StatDBEntry *dbentry);
|
||||||
static void autovac_report_activity(autovac_table *tab);
|
static void autovac_report_activity(autovac_table *tab);
|
||||||
static void avl_sighup_handler(SIGNAL_ARGS);
|
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_sigterm_handler(SIGNAL_ARGS);
|
||||||
static void avl_quickdie(SIGNAL_ARGS);
|
|
||||||
static void autovac_refresh_stats(void);
|
static void autovac_refresh_stats(void);
|
||||||
|
|
||||||
|
|
||||||
@ -407,6 +400,9 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
/* Identify myself via ps */
|
/* Identify myself via ps */
|
||||||
init_ps_display("autovacuum launcher process", "", "", "");
|
init_ps_display("autovacuum launcher process", "", "", "");
|
||||||
|
|
||||||
|
ereport(LOG,
|
||||||
|
(errmsg("autovacuum launcher started")));
|
||||||
|
|
||||||
if (PostAuthDelay)
|
if (PostAuthDelay)
|
||||||
pg_usleep(PostAuthDelay * 1000000L);
|
pg_usleep(PostAuthDelay * 1000000L);
|
||||||
|
|
||||||
@ -424,20 +420,20 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up signal handlers. Since this is an auxiliary process, it has
|
* Set up signal handlers. We operate on databases much like a regular
|
||||||
* particular signal requirements -- no deadlock checker or sinval
|
* backend, so we use the same signal handling. See equivalent code in
|
||||||
* catchup, for example.
|
* tcop/postgres.c.
|
||||||
*/
|
*/
|
||||||
pqsignal(SIGHUP, avl_sighup_handler);
|
pqsignal(SIGHUP, avl_sighup_handler);
|
||||||
|
pqsignal(SIGINT, StatementCancelHandler);
|
||||||
pqsignal(SIGINT, SIG_IGN);
|
|
||||||
pqsignal(SIGTERM, avl_sigterm_handler);
|
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(SIGPIPE, SIG_IGN);
|
||||||
pqsignal(SIGUSR1, avl_sigusr1_handler);
|
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
|
||||||
pqsignal(SIGUSR2, SIG_IGN);
|
pqsignal(SIGUSR2, avl_sigusr2_handler);
|
||||||
pqsignal(SIGFPE, FloatExceptionHandler);
|
pqsignal(SIGFPE, FloatExceptionHandler);
|
||||||
pqsignal(SIGCHLD, SIG_DFL);
|
pqsignal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
@ -451,9 +447,13 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
* had to do some stuff with LWLocks).
|
* had to do some stuff with LWLocks).
|
||||||
*/
|
*/
|
||||||
#ifndef EXEC_BACKEND
|
#ifndef EXEC_BACKEND
|
||||||
InitAuxiliaryProcess();
|
InitProcess();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
InitPostgres(NULL, InvalidOid, NULL, NULL);
|
||||||
|
|
||||||
|
SetProcessingMode(NormalProcessing);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a memory context that we will do all our work in. We do this so
|
* 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
|
* that we can reset the context during error recovery and thereby avoid
|
||||||
@ -466,11 +466,10 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
MemoryContextSwitchTo(AutovacMemCxt);
|
MemoryContextSwitchTo(AutovacMemCxt);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If an exception is encountered, processing resumes here.
|
* 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)
|
if (sigsetjmp(local_sigjmp_buf, 1) != 0)
|
||||||
{
|
{
|
||||||
@ -480,17 +479,16 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
/* Prevents interrupts while cleaning up */
|
/* Prevents interrupts while cleaning up */
|
||||||
HOLD_INTERRUPTS();
|
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 */
|
/* Report the error to the server log */
|
||||||
EmitErrorReport();
|
EmitErrorReport();
|
||||||
|
|
||||||
/*
|
/* Abort the current transaction in order to recover */
|
||||||
* These operations are really just a minimal subset of
|
AbortCurrentTransaction();
|
||||||
* AbortTransaction(). We don't have very many resources to worry
|
|
||||||
* about, but we do have LWLocks.
|
|
||||||
*/
|
|
||||||
LWLockReleaseAll();
|
|
||||||
AtEOXact_Files();
|
|
||||||
AtEOXact_HashTables(false);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now return to normal top-level context and clear ErrorContext for
|
* 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) */
|
/* We can now handle ereport(ERROR) */
|
||||||
PG_exception_stack = &local_sigjmp_buf;
|
PG_exception_stack = &local_sigjmp_buf;
|
||||||
|
|
||||||
ereport(LOG,
|
|
||||||
(errmsg("autovacuum launcher started")));
|
|
||||||
|
|
||||||
/* must unblock signals before calling rebuild_database_list */
|
/* must unblock signals before calling rebuild_database_list */
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
|
|
||||||
@ -561,11 +556,14 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
* necessity for manual cleanup of all postmaster children.
|
* necessity for manual cleanup of all postmaster children.
|
||||||
*/
|
*/
|
||||||
if (!PostmasterIsAlive(true))
|
if (!PostmasterIsAlive(true))
|
||||||
exit(1);
|
proc_exit(1);
|
||||||
|
|
||||||
launcher_determine_sleep((AutoVacuumShmem->av_freeWorkers != NULL),
|
launcher_determine_sleep((AutoVacuumShmem->av_freeWorkers != NULL),
|
||||||
false, &nap);
|
false, &nap);
|
||||||
|
|
||||||
|
/* Allow sinval catchup interrupts while sleeping */
|
||||||
|
EnableCatchupInterrupt();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sleep for a while according to schedule.
|
* Sleep for a while according to schedule.
|
||||||
*
|
*
|
||||||
@ -595,12 +593,14 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
* necessity for manual cleanup of all postmaster children.
|
* necessity for manual cleanup of all postmaster children.
|
||||||
*/
|
*/
|
||||||
if (!PostmasterIsAlive(true))
|
if (!PostmasterIsAlive(true))
|
||||||
exit(1);
|
proc_exit(1);
|
||||||
|
|
||||||
if (got_SIGTERM || got_SIGHUP || got_SIGUSR1)
|
if (got_SIGTERM || got_SIGHUP || got_SIGUSR2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisableCatchupInterrupt();
|
||||||
|
|
||||||
/* the normal shutdown case */
|
/* the normal shutdown case */
|
||||||
if (got_SIGTERM)
|
if (got_SIGTERM)
|
||||||
break;
|
break;
|
||||||
@ -610,7 +610,7 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
got_SIGHUP = false;
|
got_SIGHUP = false;
|
||||||
ProcessConfigFile(PGC_SIGHUP);
|
ProcessConfigFile(PGC_SIGHUP);
|
||||||
|
|
||||||
/* shutdown requested in config file */
|
/* shutdown requested in config file? */
|
||||||
if (!AutoVacuumingActive())
|
if (!AutoVacuumingActive())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -627,9 +627,9 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
* a worker finished, or postmaster signalled failure to start a
|
* a worker finished, or postmaster signalled failure to start a
|
||||||
* worker
|
* worker
|
||||||
*/
|
*/
|
||||||
if (got_SIGUSR1)
|
if (got_SIGUSR2)
|
||||||
{
|
{
|
||||||
got_SIGUSR1 = false;
|
got_SIGUSR2 = false;
|
||||||
|
|
||||||
/* rebalance cost limits, if needed */
|
/* rebalance cost limits, if needed */
|
||||||
if (AutoVacuumShmem->av_signal[AutoVacRebalance])
|
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
|
* 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.
|
* after calling this function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -1322,11 +1322,11 @@ avl_sighup_handler(SIGNAL_ARGS)
|
|||||||
got_SIGHUP = true;
|
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
|
static void
|
||||||
avl_sigusr1_handler(SIGNAL_ARGS)
|
avl_sigusr2_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
got_SIGUSR1 = true;
|
got_SIGUSR2 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIGTERM: time to die */
|
/* SIGTERM: time to die */
|
||||||
@ -1336,38 +1336,6 @@ avl_sigterm_handler(SIGNAL_ARGS)
|
|||||||
got_SIGTERM = true;
|
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
|
* AUTOVACUUM WORKER CODE
|
||||||
@ -1590,7 +1558,7 @@ AutoVacWorkerMain(int argc, char *argv[])
|
|||||||
|
|
||||||
/* wake up the launcher */
|
/* wake up the launcher */
|
||||||
if (AutoVacuumShmem->av_launcherpid != 0)
|
if (AutoVacuumShmem->av_launcherpid != 0)
|
||||||
kill(AutoVacuumShmem->av_launcherpid, SIGUSR1);
|
kill(AutoVacuumShmem->av_launcherpid, SIGUSR2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1784,46 +1752,57 @@ autovac_balance_cost(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* get_database_list
|
* 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,
|
* Note: this is the only function in which the autovacuum launcher uses a
|
||||||
* because we aren't connected; we use the flat database file.
|
* 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 *
|
static List *
|
||||||
get_database_list(void)
|
get_database_list(void)
|
||||||
{
|
{
|
||||||
char *filename;
|
|
||||||
List *dblist = NIL;
|
List *dblist = NIL;
|
||||||
char thisname[NAMEDATALEN];
|
Relation rel;
|
||||||
FILE *db_file;
|
HeapScanDesc scan;
|
||||||
Oid db_id;
|
HeapTuple tup;
|
||||||
Oid db_tablespace;
|
|
||||||
TransactionId db_frozenxid;
|
|
||||||
|
|
||||||
filename = database_getflatfilename();
|
/*
|
||||||
db_file = AllocateFile(filename, "r");
|
* Start a transaction so we can access pg_database, and get a snapshot.
|
||||||
if (db_file == NULL)
|
* We don't have a use for the snapshot itself, but we're interested in
|
||||||
ereport(FATAL,
|
* the secondary effect that it sets RecentGlobalXmin. (This is critical
|
||||||
(errcode_for_file_access(),
|
* for anything that reads heap pages, because HOT may decide to prune
|
||||||
errmsg("could not open file \"%s\": %m", filename)));
|
* them even if the process doesn't attempt to modify any tuples.)
|
||||||
|
*/
|
||||||
|
StartTransactionCommand();
|
||||||
|
(void) GetTransactionSnapshot();
|
||||||
|
|
||||||
while (read_pg_database_line(db_file, thisname, &db_id,
|
/* Allocate our results in AutovacMemCxt, not transaction context */
|
||||||
&db_tablespace, &db_frozenxid))
|
MemoryContextSwitchTo(AutovacMemCxt);
|
||||||
|
|
||||||
|
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 = (avw_dbase *) palloc(sizeof(avw_dbase));
|
||||||
|
|
||||||
avdb->adw_datid = db_id;
|
avdb->adw_datid = HeapTupleGetOid(tup);
|
||||||
avdb->adw_name = pstrdup(thisname);
|
avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
|
||||||
avdb->adw_frozenxid = db_frozenxid;
|
avdb->adw_frozenxid = pgdatabase->datfrozenxid;
|
||||||
/* this gets set later: */
|
/* this gets set later: */
|
||||||
avdb->adw_entry = NULL;
|
avdb->adw_entry = NULL;
|
||||||
|
|
||||||
dblist = lappend(dblist, avdb);
|
dblist = lappend(dblist, avdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeFile(db_file);
|
heap_endscan(scan);
|
||||||
pfree(filename);
|
heap_close(rel, AccessShareLock);
|
||||||
|
|
||||||
|
CommitTransactionCommand();
|
||||||
|
|
||||||
return dblist;
|
return dblist;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -1442,7 +1442,7 @@ ServerLoop(void)
|
|||||||
{
|
{
|
||||||
avlauncher_needs_signal = false;
|
avlauncher_needs_signal = false;
|
||||||
if (AutoVacPID != 0)
|
if (AutoVacPID != 0)
|
||||||
kill(AutoVacPID, SIGUSR1);
|
kill(AutoVacPID, SIGUSR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3865,7 +3865,7 @@ SubPostmasterMain(int argc, char *argv[])
|
|||||||
InitShmemAccess(UsedShmemSegAddr);
|
InitShmemAccess(UsedShmemSegAddr);
|
||||||
|
|
||||||
/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
|
/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
|
||||||
InitAuxiliaryProcess();
|
InitProcess();
|
||||||
|
|
||||||
/* Attach process to shared data structures */
|
/* Attach process to shared data structures */
|
||||||
CreateSharedMemoryAndSemaphores(false, 0);
|
CreateSharedMemoryAndSemaphores(false, 0);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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));
|
size = add_size(size, sizeof(PROC_HDR));
|
||||||
/* AuxiliaryProcs */
|
/* AuxiliaryProcs */
|
||||||
size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC)));
|
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)));
|
size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC)));
|
||||||
/* ProcStructLock */
|
/* ProcStructLock */
|
||||||
size = add_size(size, sizeof(slock_t));
|
size = add_size(size, sizeof(slock_t));
|
||||||
@ -192,19 +192,27 @@ InitProcGlobal(void)
|
|||||||
ProcGlobal->freeProcs = &procs[i];
|
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)
|
if (!procs)
|
||||||
ereport(FATAL,
|
ereport(FATAL,
|
||||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||||
errmsg("out of shared memory")));
|
errmsg("out of shared memory")));
|
||||||
MemSet(procs, 0, autovacuum_max_workers * sizeof(PGPROC));
|
MemSet(procs, 0, (autovacuum_max_workers + 1) * sizeof(PGPROC));
|
||||||
for (i = 0; i < autovacuum_max_workers; i++)
|
for (i = 0; i < autovacuum_max_workers + 1; i++)
|
||||||
{
|
{
|
||||||
PGSemaphoreCreate(&(procs[i].sem));
|
PGSemaphoreCreate(&(procs[i].sem));
|
||||||
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
|
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
|
||||||
ProcGlobal->autovacFreeProcs = &procs[i];
|
ProcGlobal->autovacFreeProcs = &procs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And auxiliary procs.
|
||||||
|
*/
|
||||||
MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC));
|
MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC));
|
||||||
for (i = 0; i < NUM_AUXILIARY_PROCS; i++)
|
for (i = 0; i < NUM_AUXILIARY_PROCS; i++)
|
||||||
{
|
{
|
||||||
@ -248,14 +256,14 @@ InitProcess(void)
|
|||||||
|
|
||||||
set_spins_per_delay(procglobal->spins_per_delay);
|
set_spins_per_delay(procglobal->spins_per_delay);
|
||||||
|
|
||||||
if (IsAutoVacuumWorkerProcess())
|
if (IsAnyAutoVacuumProcess())
|
||||||
MyProc = procglobal->autovacFreeProcs;
|
MyProc = procglobal->autovacFreeProcs;
|
||||||
else
|
else
|
||||||
MyProc = procglobal->freeProcs;
|
MyProc = procglobal->freeProcs;
|
||||||
|
|
||||||
if (MyProc != NULL)
|
if (MyProc != NULL)
|
||||||
{
|
{
|
||||||
if (IsAutoVacuumWorkerProcess())
|
if (IsAnyAutoVacuumProcess())
|
||||||
procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next;
|
procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next;
|
||||||
else
|
else
|
||||||
procglobal->freeProcs = (PGPROC *) MyProc->links.next;
|
procglobal->freeProcs = (PGPROC *) MyProc->links.next;
|
||||||
@ -278,9 +286,10 @@ InitProcess(void)
|
|||||||
/*
|
/*
|
||||||
* Now that we have a PGPROC, mark ourselves as an active postmaster
|
* 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
|
* 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();
|
MarkPostmasterChildActive();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -299,6 +308,7 @@ InitProcess(void)
|
|||||||
MyProc->roleId = InvalidOid;
|
MyProc->roleId = InvalidOid;
|
||||||
MyProc->inCommit = false;
|
MyProc->inCommit = false;
|
||||||
MyProc->vacuumFlags = 0;
|
MyProc->vacuumFlags = 0;
|
||||||
|
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
|
||||||
if (IsAutoVacuumWorkerProcess())
|
if (IsAutoVacuumWorkerProcess())
|
||||||
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
|
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
|
||||||
MyProc->lwWaiting = false;
|
MyProc->lwWaiting = false;
|
||||||
@ -429,7 +439,6 @@ InitAuxiliaryProcess(void)
|
|||||||
MyProc->databaseId = InvalidOid;
|
MyProc->databaseId = InvalidOid;
|
||||||
MyProc->roleId = InvalidOid;
|
MyProc->roleId = InvalidOid;
|
||||||
MyProc->inCommit = false;
|
MyProc->inCommit = false;
|
||||||
/* we don't set the "is autovacuum" flag in the launcher */
|
|
||||||
MyProc->vacuumFlags = 0;
|
MyProc->vacuumFlags = 0;
|
||||||
MyProc->lwWaiting = false;
|
MyProc->lwWaiting = false;
|
||||||
MyProc->lwExclusive = false;
|
MyProc->lwExclusive = false;
|
||||||
@ -595,8 +604,8 @@ ProcKill(int code, Datum arg)
|
|||||||
|
|
||||||
SpinLockAcquire(ProcStructLock);
|
SpinLockAcquire(ProcStructLock);
|
||||||
|
|
||||||
/* Return PGPROC structure (and semaphore) to freelist */
|
/* Return PGPROC structure (and semaphore) to appropriate freelist */
|
||||||
if (IsAutoVacuumWorkerProcess())
|
if (IsAnyAutoVacuumProcess())
|
||||||
{
|
{
|
||||||
MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs;
|
MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs;
|
||||||
procglobal->autovacFreeProcs = MyProc;
|
procglobal->autovacFreeProcs = MyProc;
|
||||||
@ -618,13 +627,14 @@ ProcKill(int code, Datum arg)
|
|||||||
/*
|
/*
|
||||||
* This process is no longer present in shared memory in any meaningful
|
* This process is no longer present in shared memory in any meaningful
|
||||||
* way, so tell the postmaster we've cleaned up acceptably well.
|
* 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();
|
MarkPostmasterChildInactive();
|
||||||
|
|
||||||
/* wake autovac launcher if needed -- see comments in FreeWorkerInfo */
|
/* wake autovac launcher if needed -- see comments in FreeWorkerInfo */
|
||||||
if (AutovacuumLauncherPid != 0)
|
if (AutovacuumLauncherPid != 0)
|
||||||
kill(AutovacuumLauncherPid, SIGUSR1);
|
kill(AutovacuumLauncherPid, SIGUSR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Globals used all over the place should be declared here and not
|
* 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
|
* Primary determinants of sizes of shared-memory structures. MaxBackends is
|
||||||
* MaxConnections + autovacuum_max_workers (it is computed by the GUC assign
|
* MaxConnections + autovacuum_max_workers + 1 (it is computed by the GUC
|
||||||
* hook):
|
* assign hooks for those variables):
|
||||||
*/
|
*/
|
||||||
int NBuffers = 1000;
|
int NBuffers = 1000;
|
||||||
int MaxBackends = 100;
|
int MaxBackends = 100;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* 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.
|
* 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
|
* 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
|
* 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)
|
if (!bootstrap)
|
||||||
pgstat_initialize();
|
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
|
* 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
|
* 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);
|
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
|
* 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
|
* snapshot. We don't have a use for the snapshot itself, but we're
|
||||||
* interested in the secondary effect that it sets RecentGlobalXmin.
|
* 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)
|
if (!bootstrap)
|
||||||
{
|
{
|
||||||
@ -559,12 +574,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
|||||||
(void) GetTransactionSnapshot();
|
(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.
|
* Set up the global variables holding database id and default tablespace.
|
||||||
* But note we won't actually try to touch the database just yet.
|
* But note we won't actually try to touch the database just yet.
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* Note: MaxBackends is limited to INT_MAX/4 because some places compute
|
||||||
* 4*MaxBackends without any overflow check. This check is made in
|
* 4*MaxBackends without any overflow check. This check is made in
|
||||||
* assign_maxconnections, since MaxBackends is computed as MaxConnections
|
* 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.
|
* Likewise we have to limit NBuffers to INT_MAX/2.
|
||||||
*/
|
*/
|
||||||
@ -7570,11 +7570,11 @@ show_tcp_keepalives_count(void)
|
|||||||
static bool
|
static bool
|
||||||
assign_maxconnections(int newval, bool doit, GucSource source)
|
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;
|
return false;
|
||||||
|
|
||||||
if (doit)
|
if (doit)
|
||||||
MaxBackends = newval + autovacuum_max_workers;
|
MaxBackends = newval + autovacuum_max_workers + 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -7582,11 +7582,11 @@ assign_maxconnections(int newval, bool doit, GucSource source)
|
|||||||
static bool
|
static bool
|
||||||
assign_autovacuum_max_workers(int newval, bool doit, GucSource source)
|
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;
|
return false;
|
||||||
|
|
||||||
if (doit)
|
if (doit)
|
||||||
MaxBackends = newval + MaxConnections;
|
MaxBackends = MaxConnections + newval + 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 AutoVacuumingActive(void);
|
||||||
extern bool IsAutoVacuumLauncherProcess(void);
|
extern bool IsAutoVacuumLauncherProcess(void);
|
||||||
extern bool IsAutoVacuumWorkerProcess(void);
|
extern bool IsAutoVacuumWorkerProcess(void);
|
||||||
|
#define IsAnyAutoVacuumProcess() \
|
||||||
|
(IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess())
|
||||||
|
|
||||||
/* Functions to start autovacuum process, called from postmaster */
|
/* Functions to start autovacuum process, called from postmaster */
|
||||||
extern void autovac_init(void);
|
extern void autovac_init(void);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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,
|
* We set aside some extra PGPROC structures for auxiliary processes,
|
||||||
* ie things that aren't full-fledged backends but need shmem access.
|
* ie things that aren't full-fledged backends but need shmem access.
|
||||||
*
|
*
|
||||||
* Background writer, WAL writer, and autovacuum launcher run during
|
* Background writer and WAL writer run during normal operation. Startup
|
||||||
* normal operation. Startup process also consumes one slot, but WAL
|
* process also consumes one slot, but WAL writer is launched only after
|
||||||
* writer and autovacuum launcher are launched only after it has
|
* startup has exited, so we only need 2 slots.
|
||||||
* exited.
|
|
||||||
*/
|
*/
|
||||||
#define NUM_AUXILIARY_PROCS 3
|
#define NUM_AUXILIARY_PROCS 2
|
||||||
|
|
||||||
|
|
||||||
/* configurable options */
|
/* configurable options */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user