Change the autovacuum launcher to read pg_database directly, rather than
authorTom Lane
Mon, 31 Aug 2009 19:41:00 +0000 (19:41 +0000)
committerTom Lane
Mon, 31 Aug 2009 19:41:00 +0000 (19:41 +0000)
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

src/backend/postmaster/autovacuum.c
src/backend/postmaster/postmaster.c
src/backend/storage/lmgr/proc.c
src/backend/utils/init/globals.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/include/postmaster/autovacuum.h
src/include/storage/proc.h

index ea4fe65b519d523f3ea7485af5a7312c083d1202..41bd37d72a655fdd062f428cd1e8ca5c45563e9b 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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"
 #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;
 }
index 3f7733364119f5e6b3fcf0c363f7b7c2da5cb5d1..c4d8d8ae8d71aa23382035f080509931439991b4 100644 (file)
@@ -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);
index d9a0a689f87026f2eaa4e778f2d1cea8ac47c43d..56a785d138484434f28723506bae2c3b2acea9e7 100644 (file)
@@ -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);
 }
 
 /*
index e4f5dfa5849088736c8f91a0ca12a5ae2e58ee81..fe2cef87d3e2203832325c77b0dd61cd4009ce18 100644 (file)
@@ -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;
index 11eeec353c98c999eee7844f0dfac53c4f337803..2d7253312f5f93c42caf344a5624cbc94626b765 100644 (file)
@@ -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.
index 66904e6b091c52dc961e4f7fccdcf773c8ce595b..03e2408737e849fdc5ba036b9407f569b85bc2fc 100644 (file)
@@ -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;
 }
index 3175487af3f8efd8b30c9d5608365acd0bd7a90f..dcdf57cdd42e35f250af11e6e895f702f075f652 100644 (file)
@@ -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);
index 98bb41103d2846cdd0e928e240096ebcabd3d497..c8a9042fdc86b0799a732d1cc605e4a51b048e13 100644 (file)
@@ -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 */