diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index d8ec4f9f658c53bfccfe191d7210ae17f99bec57..f938a27bb918a0ac3e4e1b571d2cc84c2cc4c307 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.110 2005/07/31 17:19:16 tgl Exp $
+ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.111 2005/08/11 21:11:41 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -1197,6 +1197,20 @@
       <entry>Multiplier for reltuples to add to
        <structfield>anl_base_thresh</></entry>
      </row>
+
+     <row>
+      <entry><structfield>vac_cost_delay</structfield></entry>
+      <entry><type>integer</type></entry>
+      <entry></entry>
+      <entry>Custom <varname>vacuum_cost_delay</> parameter</entry>
+     </row>
+
+     <row>
+      <entry><structfield>vac_cost_limit</structfield></entry>
+      <entry><type>integer</type></entry>
+      <entry></entry>
+      <entry>Custom <varname>vacuum_cost_limit</> parameter</entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
@@ -1217,7 +1231,11 @@
   <para>
    Any of the numerical fields can contain <literal>-1</> (or indeed
    any negative value) to indicate that the system-wide default should
-   be used for this particular value.
+   be used for this particular value.  Observe that the
+   <structfield>vac_cost_delay</> variable inherits its default value from the
+   <varname>autovacuum_vacuum_cost_delay</> configuration parameter,
+   or from <varname>vacuum_cost_delay</> if the former is set to a negative
+   value.  The same applies to <structfield>vac_cost_limit</>.
   </para>
 
  </sect1>
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 87a976396324f94b024409386563810a36b7ff63..060cd91ea16bae7ce50b0b52a98f83159f9d244a 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.343 2005/08/09 05:01:10 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.344 2005/08/11 21:11:42 tgl Exp $
 -->
 
 <chapter Id="runtime">
@@ -3296,7 +3296,7 @@ SELECT * FROM parent WHERE key = 2400;
        <para>
         If on, collected statistics are zeroed out whenever the server
         is restarted. If off, statistics are accumulated across server
-        restarts. The default is <literal>on</>. This option can only 
+        restarts. The default is <literal>off</>. This option can only 
         be set at server start.
        </para>
       </listitem>
@@ -3424,6 +3424,40 @@ SELECT * FROM parent WHERE key = 2400;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-autovacuum-vacuum-cost-delay" xreflabel="autovacuum_vacuum_cost_delay">
+      <term><varname>autovacuum_vacuum_cost_delay</varname> (<type>integer</type>)</term>
+      <indexterm>
+       <primary><varname>autovacuum_vacuum_cost_delay</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Specifies the cost delay value that will be used in automatic
+        <command>VACUUM</> operations.  If -1 is specified (which is the
+        default), the regular
+        <xref linkend="guc-vacuum-cost-delay"> value will be used.
+        This setting can be overridden for individual tables by entries in
+        <structname>pg_autovacuum</>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-autovacuum-vacuum-cost-limit" xreflabel="autovacuum_vacuum_cost_limit">
+      <term><varname>autovacuum_vacuum_cost_limit</varname> (<type>integer</type>)</term>
+      <indexterm>
+       <primary><varname>autovacuum_vacuum_cost_limit</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Specifies the cost limit value that will be used in automatic
+        <command>VACUUM</> operations.  If -1 is specified (which is the
+        default), the regular
+        <xref linkend="guc-vacuum-cost-limit"> value will be used.
+        This setting can be overridden for individual tables by entries in
+        <structname>pg_autovacuum</>.
+       </para>
+      </listitem>
+     </varlistentry>
+
     </variablelist>
    </sect2>
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index d1e36652b2d09c7442ee8993bd50b82adcf671b1..ae57ec0231a628e8820b31d60968a4bf851d665b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.214 2005/07/30 14:15:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.215 2005/08/11 21:11:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "postmaster/bgwriter.h"
 #include "storage/bufpage.h"
 #include "storage/fd.h"
@@ -48,7 +49,7 @@
 
 
 /*
- *	Becauase O_DIRECT bypasses the kernel buffers, and because we never
+ *	Because O_DIRECT bypasses the kernel buffers, and because we never
  *	read those buffers except during crash recovery, it is a win to use
  *	it in all cases where we sync on each write().  We could allow O_DIRECT
  *	with fsync(), but because skipping the kernel buffer forces writes out
@@ -4685,6 +4686,11 @@ StartupXLOG(void)
 				RmgrTable[rmid].rm_cleanup();
 		}
 
+		/*
+		 * Reset pgstat data, because it may be invalid after recovery.
+		 */
+		pgstat_reset_all();
+
 		/*
 		 * Perform a new checkpoint to update our recovery activity to
 		 * disk.
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 717b398f89355f2b1c1f3e78b96bfe258d38b790..f565442ac68f2fed728425370de26d8dd3fd9b34 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.146 2005/07/29 19:30:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.147 2005/08/11 21:11:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1001,13 +1001,15 @@ load_hba(void)
  *	dboid: gets database OID
  *	dbtablespace: gets database's default tablespace's OID
  *	dbfrozenxid: gets database's frozen XID
+ *	dbvacuumxid: gets database's vacuum XID
  *
  * This is not much related to the other functions in hba.c, but we put it
  * here because it uses the next_token() infrastructure.
  */
 bool
 read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
-					  Oid *dbtablespace, TransactionId *dbfrozenxid)
+					  Oid *dbtablespace, TransactionId *dbfrozenxid,
+					  TransactionId *dbvacuumxid)
 {
 	char		buf[MAX_TOKEN];
 
@@ -1030,6 +1032,10 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
 	if (!isdigit((unsigned char) buf[0]))
 		elog(FATAL, "bad data in flat pg_database file");
 	*dbfrozenxid = atoxid(buf);
+	next_token(fp, buf, sizeof(buf));
+	if (!isdigit((unsigned char) buf[0]))
+		elog(FATAL, "bad data in flat pg_database file");
+	*dbvacuumxid = atoxid(buf);
 	/* expect EOL next */
 	if (next_token(fp, buf, sizeof(buf)))
 		elog(FATAL, "bad data in flat pg_database file");
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 10eb9b6da88bf6eb777f61093d625256ebd06af2..3b3093727f1bbe1d39a924e137e9133e706a24b7 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.2 2005/07/29 19:30:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.3 2005/08/11 21:11:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_autovacuum.h"
+#include "catalog/pg_database.h"
 #include "commands/vacuum.h"
 #include "libpq/hba.h"
 #include "libpq/pqsignal.h"
@@ -57,6 +58,9 @@ double		autovacuum_vac_scale;
 int			autovacuum_anl_thresh;
 double		autovacuum_anl_scale;
 
+int			autovacuum_vac_cost_delay;
+int			autovacuum_vac_cost_limit;
+
 /* Flag to tell if we are in the autovacuum daemon process */
 static bool am_autovacuum = false;
 
@@ -64,27 +68,43 @@ static bool am_autovacuum = false;
 static time_t last_autovac_start_time = 0;
 static time_t last_autovac_stop_time = 0;
 
+/* Memory context for long-lived data */
+static MemoryContext	AutovacMemCxt;
+
 /* struct to keep list of candidate databases for vacuum */
 typedef struct autovac_dbase
 {
 	Oid				oid;
 	char		   *name;
 	TransactionId	frozenxid;
+	TransactionId	vacuumxid;
 	PgStat_StatDBEntry *entry;
 	int32			age;
 } autovac_dbase;
 
+/* struct to keep track of tables to vacuum and/or analyze */
+typedef struct autovac_table
+{
+	Oid			relid;
+	bool		dovacuum;
+	bool		doanalyze;
+	int			vacuum_cost_delay;
+	int			vacuum_cost_limit;
+} autovac_table;
+
 
 #ifdef EXEC_BACKEND
 static pid_t autovac_forkexec(void);
 #endif
 NON_EXEC_STATIC void AutoVacMain(int argc, char *argv[]);
-static void do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry);
+static void process_whole_db(void);
+static void do_autovacuum(PgStat_StatDBEntry *dbentry);
 static List *autovac_get_database_list(void);
 static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 			 Form_pg_class classForm, Form_pg_autovacuum avForm,
-			 List **vacuum_tables, List **analyze_tables);
-static void autovacuum_do_vac_analyze(List *relids, bool dovacuum);
+			 List **vacuum_tables);
+static void autovacuum_do_vac_analyze(List *relids, bool dovacuum,
+									  bool doanalyze, bool freeze);
 
 
 /*
@@ -210,6 +230,12 @@ AutoVacMain(int argc, char *argv[])
 	/* Lose the postmaster's on-exit routines */
 	on_exit_reset();
 
+	/* Identify myself via ps */
+	init_ps_display("autovacuum process", "", "");
+	set_ps_display("");
+
+	SetProcessingMode(InitProcessing);
+
 	/*
 	 * Set up signal handlers.  We operate on databases much like a
 	 * regular backend, so we use the same signal handling.  See
@@ -233,12 +259,9 @@ AutoVacMain(int argc, char *argv[])
 	pqsignal(SIGUSR1, CatchupInterruptHandler);
 	/* We don't listen for async notifies */
 	pqsignal(SIGUSR2, SIG_IGN);
+	pqsignal(SIGFPE, FloatExceptionHandler);
 	pqsignal(SIGCHLD, SIG_DFL);
 
-	/* Identify myself via ps */
-	init_ps_display("autovacuum process", "", "");
-	set_ps_display("");
-
 	/* Early initialization */
 	BaseInit();
 
@@ -302,6 +325,8 @@ AutoVacMain(int argc, char *argv[])
 	{
 		autovac_dbase  *tmp = lfirst(cell);
 		bool			this_whole_db;
+		int32			freeze_age,
+						vacuum_age;
 
 		/*
 		 * We look for the database that most urgently needs a database-wide
@@ -309,9 +334,16 @@ AutoVacMain(int argc, char *argv[])
 		 * transactions sooner than vacuum.c's vac_truncate_clog() would
 		 * decide to start giving warnings.  If any such db is found, we
 		 * ignore all other dbs.
+		 *
+		 * Unlike vacuum.c, we also look at vacuumxid.  This is so that
+		 * pg_clog can be kept trimmed to a reasonable size.
 		 */
-		tmp->age = (int32) (nextXid - tmp->frozenxid);
-		this_whole_db = (tmp->age > (int32) ((MaxTransactionId >> 3) * 3 - 100000));
+		freeze_age = (int32) (nextXid - tmp->frozenxid);
+		vacuum_age = (int32) (nextXid - tmp->vacuumxid);
+		tmp->age = Max(freeze_age, vacuum_age);
+
+		this_whole_db = (tmp->age >
+						 (int32) ((MaxTransactionId >> 3) * 3 - 100000));
 		if (whole_db || this_whole_db)
 		{
 			if (!this_whole_db)
@@ -363,10 +395,21 @@ AutoVacMain(int argc, char *argv[])
 		set_ps_display(db->name);
 		ereport(LOG,
 				(errmsg("autovacuum: processing database \"%s\"", db->name)));
+
+		/* Create the memory context where cross-transaction state is stored */
+		AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
+											  "Autovacuum context",
+											  ALLOCSET_DEFAULT_MINSIZE,
+											  ALLOCSET_DEFAULT_INITSIZE,
+											  ALLOCSET_DEFAULT_MAXSIZE);
+
 		/*
-		 * And do an appropriate amount of work on it
+		 * And do an appropriate amount of work
 		 */
-		do_autovacuum(whole_db, db->entry);
+		if (whole_db)
+			process_whole_db();
+		else
+			do_autovacuum(db->entry);
 	}
 
 	/* One iteration done, go away */
@@ -389,6 +432,7 @@ autovac_get_database_list(void)
 	Oid		db_id;
 	Oid		db_tablespace;
 	TransactionId db_frozenxid;
+	TransactionId db_vacuumxid;
 
 	filename = database_getflatfilename();
 	db_file = AllocateFile(filename, "r");
@@ -398,7 +442,8 @@ autovac_get_database_list(void)
 				 errmsg("could not open file \"%s\": %m", filename)));
 
 	while (read_pg_database_line(db_file, thisname, &db_id,
-								 &db_tablespace, &db_frozenxid))
+								 &db_tablespace, &db_frozenxid,
+								 &db_vacuumxid))
 	{
 		autovac_dbase	*db;
 
@@ -407,6 +452,7 @@ autovac_get_database_list(void)
 		db->oid = db_id;
 		db->name = pstrdup(thisname);
 		db->frozenxid = db_frozenxid;
+		db->vacuumxid = db_vacuumxid;
 		/* these get set later: */
 		db->entry = NULL;
 		db->age = 0;
@@ -421,40 +467,79 @@ autovac_get_database_list(void)
 }
 
 /*
- * Process a database.
- *
- * If whole_db is true, the database is processed as a whole, and the
- * dbentry parameter is ignored.  If it's false, dbentry must be a valid
- * pointer to the database entry in the stats databases' hash table, and
- * it will be used to determine whether vacuum or analyze is needed on a
- * per-table basis.
+ * Process a whole database.  If it's a template database or is disallowing
+ * connection by means of datallowconn=false, then issue a VACUUM FREEZE.
+ * Else use a plain VACUUM.
+ */
+static void
+process_whole_db(void)
+{
+	Relation		dbRel;
+	ScanKeyData		entry[1];
+	SysScanDesc		scan;
+	HeapTuple		tup;
+	Form_pg_database dbForm;
+	bool			freeze;
+
+	/* Start a transaction so our commands have one to play into. */
+	StartTransactionCommand();
+
+	dbRel = heap_open(DatabaseRelationId, AccessShareLock);
+
+	/* Must use a table scan, since there's no syscache for pg_database */
+	ScanKeyInit(&entry[0],
+				ObjectIdAttributeNumber,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(MyDatabaseId));
+
+	scan = systable_beginscan(dbRel, DatabaseOidIndexId, true,
+							  SnapshotNow, 1, entry);
+
+	tup = systable_getnext(scan);
+
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
+
+	dbForm = (Form_pg_database) GETSTRUCT(tup);
+
+	if (!dbForm->datallowconn || dbForm->datistemplate)
+		freeze = true;
+	else
+		freeze = false;
+
+	systable_endscan(scan);
+
+	heap_close(dbRel, AccessShareLock);
+
+	elog(DEBUG2, "autovacuum: VACUUM%s whole database",
+		 (freeze) ? " FREEZE" : "");
+
+	autovacuum_do_vac_analyze(NIL, true, false, freeze);
+
+	/* Finally close out the last transaction. */
+	CommitTransactionCommand();
+}
+
+/*
+ * Process a database table-by-table
  *
- * Note that test_rel_for_autovac generates two separate lists, one for
- * vacuum and other for analyze.  This is to facilitate processing all
- * analyzes first, and then all vacuums.
+ * dbentry must be a valid pointer to the database entry in the stats
+ * databases' hash table, and it will be used to determine whether vacuum or
+ * analyze is needed on a per-table basis.
  *
  * Note that CHECK_FOR_INTERRUPTS is supposed to be used in certain spots in
  * order not to ignore shutdown commands for too long.
  */
 static void
-do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
+do_autovacuum(PgStat_StatDBEntry *dbentry)
 {
 	Relation		classRel,
 					avRel;
 	HeapTuple		tuple;
 	HeapScanDesc	relScan;
-	List		   *vacuum_tables = NIL,
-				   *analyze_tables = NIL;
-	MemoryContext	AutovacMemCxt;
-
-	Assert(whole_db || PointerIsValid(dbentry));
-
-	/* Memory context where cross-transaction state is stored */
-	AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
-										  "Autovacuum context",
-										  ALLOCSET_DEFAULT_MINSIZE,
-										  ALLOCSET_DEFAULT_INITSIZE,
-										  ALLOCSET_DEFAULT_MAXSIZE);
+	List		   *vacuum_tables = NIL;
+	ListCell *cell;
+	PgStat_StatDBEntry *shared;
 
 	/* Start a transaction so our commands have one to play into. */
 	StartTransactionCommand();
@@ -467,93 +552,87 @@ do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
 	 */
 	MemoryContextSwitchTo(AutovacMemCxt);
 
-	if (whole_db)
-	{
-		elog(DEBUG2, "autovacuum: VACUUM ANALYZE whole database");
-		autovacuum_do_vac_analyze(NIL, true);
-	}
-	else
-	{
-		/* the hash entry where pgstat stores shared relations */
-		PgStat_StatDBEntry *shared = pgstat_fetch_stat_dbentry(InvalidOid);
-
-		classRel = heap_open(RelationRelationId, AccessShareLock);
-		avRel = heap_open(AutovacuumRelationId, AccessShareLock);
-
-		relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL);
+	/* The database hash where pgstat keeps shared relations */
+	shared = pgstat_fetch_stat_dbentry(InvalidOid);
 
-		/* Scan pg_class looking for tables to vacuum */
-		while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
-		{
-			Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
-			Form_pg_autovacuum avForm = NULL;
-			PgStat_StatTabEntry *tabentry;
-			SysScanDesc	avScan;
-			HeapTuple	avTup;
-			ScanKeyData	entry[1];
-			Oid			relid;
-
-			/* Skip non-table entries. */
-			/* XXX possibly allow RELKIND_TOASTVALUE entries here too? */
-			if (classForm->relkind != RELKIND_RELATION)
-				continue;
+	classRel = heap_open(RelationRelationId, AccessShareLock);
+	avRel = heap_open(AutovacuumRelationId, AccessShareLock);
 
-			/*
-			 * Skip temp tables (i.e. those in temp namespaces).  We cannot
-			 * safely process other backends' temp tables.
-			 */
-			if (isTempNamespace(classForm->relnamespace))
-				continue;
+	relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL);
 
-			relid = HeapTupleGetOid(tuple);
+	/* Scan pg_class looking for tables to vacuum */
+	while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
+	{
+		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
+		Form_pg_autovacuum avForm = NULL;
+		PgStat_StatTabEntry *tabentry;
+		SysScanDesc	avScan;
+		HeapTuple	avTup;
+		ScanKeyData	entry[1];
+		Oid			relid;
+
+		/* Skip non-table entries. */
+		/* XXX possibly allow RELKIND_TOASTVALUE entries here too? */
+		if (classForm->relkind != RELKIND_RELATION)
+			continue;
 
-			/* See if we have a pg_autovacuum entry for this relation. */
-			ScanKeyInit(&entry[0],
-						Anum_pg_autovacuum_vacrelid,
-						BTEqualStrategyNumber, F_OIDEQ,
-						ObjectIdGetDatum(relid));
+		/*
+		 * Skip temp tables (i.e. those in temp namespaces).  We cannot
+		 * safely process other backends' temp tables.
+		 */
+		if (isTempNamespace(classForm->relnamespace))
+			continue;
 
-			avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
-										SnapshotNow, 1, entry);
+		relid = HeapTupleGetOid(tuple);
 
-			avTup = systable_getnext(avScan);
+		/* See if we have a pg_autovacuum entry for this relation. */
+		ScanKeyInit(&entry[0],
+					Anum_pg_autovacuum_vacrelid,
+					BTEqualStrategyNumber, F_OIDEQ,
+					ObjectIdGetDatum(relid));
 
-			if (HeapTupleIsValid(avTup))
-				avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
+		avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
+									SnapshotNow, 1, entry);
 
-			if (classForm->relisshared && PointerIsValid(shared))
-				tabentry = hash_search(shared->tables, &relid,
-									   HASH_FIND, NULL);
-			else
-				tabentry = hash_search(dbentry->tables, &relid,
-									   HASH_FIND, NULL);
+		avTup = systable_getnext(avScan);
 
-			test_rel_for_autovac(relid, tabentry, classForm, avForm,
-								 &vacuum_tables, &analyze_tables);
+		if (HeapTupleIsValid(avTup))
+			avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
 
-			systable_endscan(avScan);
-		}
+		if (classForm->relisshared && PointerIsValid(shared))
+			tabentry = hash_search(shared->tables, &relid,
+								   HASH_FIND, NULL);
+		else
+			tabentry = hash_search(dbentry->tables, &relid,
+								   HASH_FIND, NULL);
 
-		heap_endscan(relScan);
-		heap_close(avRel, AccessShareLock);
-		heap_close(classRel, AccessShareLock);
+		test_rel_for_autovac(relid, tabentry, classForm, avForm,
+							 &vacuum_tables);
 
-		CHECK_FOR_INTERRUPTS();
+		systable_endscan(avScan);
+	}
 
-		/*
-		 * Perform operations on collected tables.
-		 */
+	heap_endscan(relScan);
+	heap_close(avRel, AccessShareLock);
+	heap_close(classRel, AccessShareLock);
 
-		if (analyze_tables)
-			autovacuum_do_vac_analyze(analyze_tables, false);
+	/*
+	 * Perform operations on collected tables.
+	 */
+	foreach(cell, vacuum_tables)
+	{
+		autovac_table *tab = lfirst(cell);
 
 		CHECK_FOR_INTERRUPTS();
 
-		/* get back to proper context */
-		MemoryContextSwitchTo(AutovacMemCxt);
+		/* Set the vacuum cost parameters for this table */
+		VacuumCostDelay = tab->vacuum_cost_delay;
+		VacuumCostLimit = tab->vacuum_cost_limit;
 
-		if (vacuum_tables)
-			autovacuum_do_vac_analyze(vacuum_tables, true);
+		autovacuum_do_vac_analyze(list_make1_oid(tab->relid),
+								  tab->dovacuum,
+								  tab->doanalyze,
+								  false);
 	}
 
 	/* Finally close out the last transaction. */
@@ -564,7 +643,7 @@ do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
  * test_rel_for_autovac
  *
  * Check whether a table needs to be vacuumed or analyzed.  Add it to the
- * respective list if so.
+ * output list if so.
  *
  * A table needs to be vacuumed if the number of dead tuples exceeds a
  * threshold.  This threshold is calculated as
@@ -591,7 +670,7 @@ static void
 test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 					 Form_pg_class classForm,
 					 Form_pg_autovacuum avForm,
-					 List **vacuum_tables, List **analyze_tables)
+					 List **vacuum_tables)
 {
 	Relation		rel;
 	float4			reltuples;	/* pg_class.reltuples */
@@ -606,6 +685,11 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 	/* number of vacuum (resp. analyze) tuples at this time */
 	float4			vactuples,
 					anltuples;
+	/* cost-based vacuum delay parameters */
+	int				vac_cost_limit;
+	int				vac_cost_delay;
+	bool			dovacuum;
+	bool			doanalyze;
 
 	/* User disabled it in pg_autovacuum? */
 	if (avForm && !avForm->enabled)
@@ -636,15 +720,25 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 	 */
 	if (avForm != NULL)
 	{
-		vac_scale_factor = (avForm->vac_scale_factor < 0) ?
-			autovacuum_vac_scale : avForm->vac_scale_factor;
-		vac_base_thresh = (avForm->vac_base_thresh < 0) ?
-			autovacuum_vac_thresh : avForm->vac_base_thresh;
-
-		anl_scale_factor = (avForm->anl_scale_factor < 0) ?
-			autovacuum_anl_scale : avForm->anl_scale_factor;
-		anl_base_thresh = (avForm->anl_base_thresh < 0) ?
-			autovacuum_anl_thresh : avForm->anl_base_thresh;
+		vac_scale_factor = (avForm->vac_scale_factor >= 0) ?
+			avForm->vac_scale_factor : autovacuum_vac_scale;
+		vac_base_thresh = (avForm->vac_base_thresh >= 0) ?
+			avForm->vac_base_thresh : autovacuum_vac_thresh;
+
+		anl_scale_factor = (avForm->anl_scale_factor >= 0) ?
+			avForm->anl_scale_factor : autovacuum_anl_scale;
+		anl_base_thresh = (avForm->anl_base_thresh >= 0) ?
+			avForm->anl_base_thresh : autovacuum_anl_thresh;
+
+		vac_cost_limit = (avForm->vac_cost_limit >= 0) ?
+			avForm->vac_cost_limit :
+			((autovacuum_vac_cost_limit >= 0) ?
+			 autovacuum_vac_cost_limit : VacuumCostLimit);
+
+		vac_cost_delay = (avForm->vac_cost_delay >= 0) ?
+			avForm->vac_cost_delay :
+			((autovacuum_vac_cost_delay >= 0) ?
+			 autovacuum_vac_cost_delay : VacuumCostDelay);
 	}
 	else
 	{
@@ -653,6 +747,12 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 
 		anl_scale_factor = autovacuum_anl_scale;
 		anl_base_thresh = autovacuum_anl_thresh;
+
+		vac_cost_limit = (autovacuum_vac_cost_limit >= 0) ?
+			autovacuum_vac_cost_limit : VacuumCostLimit;
+
+		vac_cost_delay = (autovacuum_vac_cost_delay >= 0) ?
+			autovacuum_vac_cost_delay : VacuumCostDelay;
 	}
 
 	vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
@@ -668,22 +768,33 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 		 RelationGetRelationName(rel),
 		 vactuples, vacthresh, anltuples, anlthresh);
 
+	Assert(CurrentMemoryContext == AutovacMemCxt);
+
 	/* Determine if this table needs vacuum or analyze. */
-	if (vactuples > vacthresh)
+	dovacuum = (vactuples > vacthresh);
+	doanalyze = (anltuples > anlthresh);
+
+	/* ANALYZE refuses to work with pg_statistics */
+	if (relid == StatisticRelationId)
+		doanalyze = false;
+
+	if (dovacuum || doanalyze)
 	{
-		elog(DEBUG2, "will VACUUM ANALYZE %s",
+		autovac_table *tab;
+
+		elog(DEBUG2, "will%s%s %s",
+			 (dovacuum ? " VACUUM" : ""),
+			 (doanalyze ? " ANALYZE" : ""),
 			 RelationGetRelationName(rel));
-		*vacuum_tables = lappend_oid(*vacuum_tables, relid);
-	}
-	else if (anltuples > anlthresh)
-	{
-		/* ANALYZE refuses to work with pg_statistics */
-		if (relid != StatisticRelationId)
-		{
-			elog(DEBUG2, "will ANALYZE %s",
-					RelationGetRelationName(rel));
-			*analyze_tables = lappend_oid(*analyze_tables, relid);
-		}
+
+		tab = (autovac_table *) palloc(sizeof(autovac_table));
+		tab->relid = relid;
+		tab->dovacuum = dovacuum;
+		tab->doanalyze = doanalyze;
+		tab->vacuum_cost_limit = vac_cost_limit;
+		tab->vacuum_cost_delay = vac_cost_delay;
+
+		*vacuum_tables = lappend(*vacuum_tables, tab);
 	}
 
 	RelationClose(rel);
@@ -691,14 +802,22 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
 
 /*
  * autovacuum_do_vac_analyze
- * 		Vacuum or analyze a list of tables; or all tables if relids = NIL
- *
- * We must be in AutovacMemCxt when this routine is called.
+ * 		Vacuum and/or analyze a list of tables; or all tables if relids = NIL
  */
 static void
-autovacuum_do_vac_analyze(List *relids, bool dovacuum)
+autovacuum_do_vac_analyze(List *relids, bool dovacuum, bool doanalyze,
+						  bool freeze)
 {
-	VacuumStmt		*vacstmt = makeNode(VacuumStmt);
+	VacuumStmt	   *vacstmt;
+	MemoryContext	old_cxt;
+	
+	/*
+	 * The node must survive transaction boundaries, so make sure we create it
+	 * in a long-lived context
+	 */
+	old_cxt = MemoryContextSwitchTo(AutovacMemCxt);
+	
+	vacstmt = makeNode(VacuumStmt);
 
 	/*
 	 * Point QueryContext to the autovac memory context to fake out the
@@ -710,13 +829,16 @@ autovacuum_do_vac_analyze(List *relids, bool dovacuum)
 	/* Set up command parameters */
 	vacstmt->vacuum = dovacuum;
 	vacstmt->full = false;
-	vacstmt->analyze = true;
-	vacstmt->freeze = false;
+	vacstmt->analyze = doanalyze;
+	vacstmt->freeze = freeze;
 	vacstmt->verbose = false;
 	vacstmt->relation = NULL;	/* all tables, or not used if relids != NIL */
 	vacstmt->va_cols = NIL;
 
 	vacuum(vacstmt, relids);
+
+	pfree(vacstmt);
+	MemoryContextSwitchTo(old_cxt);
 }
 
 /*
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 00ed7b837da71ccbb1c7a1aa848efef92ab8248b..bbb1027fa2021b3f3d5f3ec724085dd94e28f5dd 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2005, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.104 2005/08/09 21:14:55 tgl Exp $
+ *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.105 2005/08/11 21:11:44 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -100,7 +100,7 @@
  * ----------
  */
 bool		pgstat_collect_startcollector = true;
-bool		pgstat_collect_resetonpmstart = true;
+bool		pgstat_collect_resetonpmstart = false;
 bool		pgstat_collect_querystring = false;
 bool		pgstat_collect_tuplelevel = false;
 bool		pgstat_collect_blocklevel = false;
@@ -237,7 +237,7 @@ pgstat_init(void)
 	 * statistics on postmaster start, simply remove the stats file.
 	 */
 	if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart)
-		unlink(PGSTAT_STAT_FILENAME);
+		pgstat_reset_all();
 
 	/*
 	 * Nothing else required if collector will not get started
@@ -456,6 +456,18 @@ startup_failed:
 	pgstat_collect_blocklevel = false;
 }
 
+/*
+ * pgstat_reset_all() -
+ *
+ * Remove the stats file.  This is used on server start if the 
+ * stats_reset_on_server_start feature is enabled, or if WAL
+ * recovery is needed after a crash.
+ */
+void
+pgstat_reset_all(void)
+{
+	unlink(PGSTAT_STAT_FILENAME);
+}
 
 #ifdef EXEC_BACKEND
 
@@ -677,11 +689,19 @@ pgstat_bestart(void)
 	if (pgStatSock < 0)
 		return;
 
-	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);
-	msg.m_databaseid = MyDatabaseId;
-	msg.m_userid = GetSessionUserId();
-	memcpy(&msg.m_clientaddr, &MyProcPort->raddr, sizeof(msg.m_clientaddr));
-	pgstat_send(&msg, sizeof(msg));
+	/*
+	 * We may not have a MyProcPort (eg, if this is the autovacuum process).
+	 * For the moment, punt and don't send BESTART --- would be better to
+	 * work out a clean way of handling "unknown clientaddr".
+	 */
+	if (MyProcPort)
+	{
+		pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);
+		msg.m_databaseid = MyDatabaseId;
+		msg.m_userid = GetSessionUserId();
+		memcpy(&msg.m_clientaddr, &MyProcPort->raddr, sizeof(msg.m_clientaddr));
+		pgstat_send(&msg, sizeof(msg));
+	}
 
 	/*
 	 * Set up a process-exit hook to ensure we flush the last batch of
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 091fbeed0b61fb2c7170ca3e396ca1ccc369dfc6..110b5816c4e32d7a48e80757835d31dea6cbe323 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.461 2005/07/29 19:30:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.462 2005/08/11 21:11:44 tgl Exp $
  *
  * NOTES
  *
@@ -342,6 +342,7 @@ typedef struct
 	int syslogPipe[2];
 #endif
 	char my_exec_path[MAXPGPATH];
+	char pkglib_path[MAXPGPATH];
 	char ExtraOptions[MAXPGPATH];
 	char lc_collate[LOCALE_NAME_BUFLEN];
 	char lc_ctype[LOCALE_NAME_BUFLEN];
@@ -3702,6 +3703,8 @@ save_backend_variables(BackendParameters *param, Port *port,
 
 	StrNCpy(param->my_exec_path, my_exec_path, MAXPGPATH);
 
+	StrNCpy(param->pkglib_path, pkglib_path, MAXPGPATH);
+
 	StrNCpy(param->ExtraOptions, ExtraOptions, MAXPGPATH);
 
 	StrNCpy(param->lc_collate, setlocale(LC_COLLATE, NULL), LOCALE_NAME_BUFLEN);
@@ -3903,6 +3906,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
 
 	StrNCpy(my_exec_path, param->my_exec_path, MAXPGPATH);
 
+	StrNCpy(pkglib_path, param->pkglib_path, MAXPGPATH);
+
 	StrNCpy(ExtraOptions, param->ExtraOptions, MAXPGPATH);
 
 	setlocale(LC_COLLATE, param->lc_collate);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 5025ab8f56ceab57c9469d9bddc65d290b41d2cd..aa0da207a3aa0fa156853fe91ca76c056aaf362c 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.456 2005/08/08 03:12:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.457 2005/08/11 21:11:45 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -162,7 +162,6 @@ static List *pg_rewrite_queries(List *querytree_list);
 static void start_xact_command(void);
 static void finish_xact_command(void);
 static void SigHupHandler(SIGNAL_ARGS);
-static void FloatExceptionHandler(SIGNAL_ARGS);
 static void log_disconnections(int code, Datum arg);
 
 
@@ -2151,7 +2150,7 @@ StatementCancelHandler(SIGNAL_ARGS)
 }
 
 /* signal handler for floating point exception */
-static void
+void
 FloatExceptionHandler(SIGNAL_ARGS)
 {
 	ereport(ERROR,
diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c
index 7087a9887d413a9b76751926eca9e10d7e1e4532..7d9d2e6cb25f678e8428e0ebfdb1bb519864242f 100644
--- a/src/backend/utils/init/flatfiles.c
+++ b/src/backend/utils/init/flatfiles.c
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.13 2005/07/28 22:27:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.14 2005/08/11 21:11:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -208,12 +208,14 @@ write_database_file(Relation drel)
 		char	   *datname;
 		Oid			datoid;
 		Oid			dattablespace;
-		TransactionId datfrozenxid;
+		TransactionId datfrozenxid,
+					  datvacuumxid;
 
 		datname = NameStr(dbform->datname);
 		datoid = HeapTupleGetOid(tuple);
 		dattablespace = dbform->dattablespace;
 		datfrozenxid = dbform->datfrozenxid;
+		datvacuumxid = dbform->datvacuumxid;
 
 		/*
 		 * Identify the oldest datfrozenxid, ignoring databases that are not
@@ -242,13 +244,14 @@ write_database_file(Relation drel)
 		}
 
 		/*
-		 * The file format is: "dbname" oid tablespace frozenxid
+		 * The file format is: "dbname" oid tablespace frozenxid vacuumxid
 		 *
-		 * The xid is not needed for backend startup, but may be of use
-		 * for forensic purposes.
+		 * The xids are not needed for backend startup, but are of use to
+		 * autovacuum, and might also be helpful for forensic purposes.
 		 */
 		fputs_quote(datname, fp);
-		fprintf(fp, " %u %u %u\n", datoid, dattablespace, datfrozenxid);
+		fprintf(fp, " %u %u %u %u\n",
+				datoid, dattablespace, datfrozenxid, datvacuumxid);
 	}
 	heap_endscan(scan);
 
@@ -654,8 +657,10 @@ write_auth_file(Relation rel_authid, Relation rel_authmem)
  * base backup which may be far out of sync with the current state.
  *
  * In theory we could skip rebuilding the flat files if no WAL replay
- * occurred, but it seems safest to just do it always.  We have to
- * scan pg_database to compute the XID wrap limit anyway.
+ * occurred, but it seems best to just do it always.  We have to
+ * scan pg_database to compute the XID wrap limit anyway.  Also, this
+ * policy means we need not force initdb to change the format of the
+ * flat files.
  *
  * In a standalone backend we pass database_only = true to skip processing
  * the auth file.  We won't need it, and building it could fail if there's
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 058872a73f252d6a81dd370f8d1fdc1c6380833c..73fedbdd477d062697854e0b2c5302794c612266 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.156 2005/08/08 03:12:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.157 2005/08/11 21:11:46 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -20,8 +20,10 @@
 #include <math.h>
 #include <unistd.h>
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "catalog/catalog.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_database.h"
@@ -79,7 +81,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
 	char	   *filename;
 	FILE	   *db_file;
 	char		thisname[NAMEDATALEN];
-	TransactionId frozenxid;
+	TransactionId dummyxid;
 
 	filename = database_getflatfilename();
 	db_file = AllocateFile(filename, "r");
@@ -89,7 +91,8 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
 				 errmsg("could not open file \"%s\": %m", filename)));
 
 	while (read_pg_database_line(db_file, thisname, db_id,
-								 db_tablespace, &frozenxid))
+								 db_tablespace, &dummyxid,
+								 &dummyxid))
 	{
 		if (strcmp(thisname, name) == 0)
 		{
@@ -131,7 +134,7 @@ static void
 ReverifyMyDatabase(const char *name)
 {
 	Relation	pgdbrel;
-	HeapScanDesc pgdbscan;
+	SysScanDesc	pgdbscan;
 	ScanKeyData key;
 	HeapTuple	tup;
 	Form_pg_database dbform;
@@ -147,9 +150,10 @@ ReverifyMyDatabase(const char *name)
 				BTEqualStrategyNumber, F_NAMEEQ,
 				NameGetDatum(name));
 
-	pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
+	pgdbscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,
+								  SnapshotNow, 1, &key);
 
-	tup = heap_getnext(pgdbscan, ForwardScanDirection);
+	tup = systable_getnext(pgdbscan);
 	if (!HeapTupleIsValid(tup) ||
 		HeapTupleGetOid(tup) != MyDatabaseId)
 	{
@@ -238,7 +242,7 @@ ReverifyMyDatabase(const char *name)
 		}
 	}
 
-	heap_endscan(pgdbscan);
+	systable_endscan(pgdbscan);
 	heap_close(pgdbrel, RowShareLock);
 }
 
@@ -428,6 +432,18 @@ InitPostgres(const char *dbname, const char *username)
 	/* Initialize portal manager */
 	EnablePortalManager();
 
+	/*
+	 * 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 manager, because during shutdown this has to
+	 * run before the low-level modules start to close down.  On the
+	 * other hand, we want it in place before we begin our first
+	 * transaction --- if we fail during the initialization transaction,
+	 * as is entirely possible, we need the AbortTransaction call to
+	 * clean up.
+	 */
+	on_shmem_exit(ShutdownPostgres, 0);
+
 	/* start a new transaction here before access to db */
 	if (!bootstrap)
 		StartTransactionCommand();
@@ -465,7 +481,8 @@ InitPostgres(const char *dbname, const char *username)
 	/*
 	 * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
 	 * got a correct result.  We can't do this until all the
-	 * database-access infrastructure is up.
+	 * database-access infrastructure is up.  (Also, it wants to know if
+	 * the user is a superuser, so the above stuff has to happen first.)
 	 */
 	if (!bootstrap)
 		ReverifyMyDatabase(dbname);
@@ -509,24 +526,10 @@ InitPostgres(const char *dbname, const char *username)
 	/* initialize client encoding */
 	InitializeClientEncoding();
 
-	/*
-	 * Initialize statistics collection for this backend.  We do this
-	 * here because the shutdown hook it sets up needs to be invoked
-	 * at the corresponding phase of backend shutdown: after
-	 * ShutdownPostgres and before we drop access to shared memory.
-	 */
+	/* initialize statistics collection for this backend */
 	if (IsUnderPostmaster)
 		pgstat_bestart();
 
-	/*
-	 * Set up process-exit callback to do pre-shutdown cleanup.  This
-	 * should be last because we want shmem_exit to call this routine
-	 * before the exit callbacks that are registered by buffer manager,
-	 * lock manager, etc. We need to run this code before we close down
-	 * database access!
-	 */
-	on_shmem_exit(ShutdownPostgres, 0);
-
 	/* close the transaction we started above */
 	if (!bootstrap)
 		CommitTransactionCommand();
@@ -538,9 +541,7 @@ InitPostgres(const char *dbname, const char *username)
 /*
  * Backend-shutdown callback.  Do cleanup that we want to be sure happens
  * before all the supporting modules begin to nail their doors shut via
- * their own callbacks.  Note that because this has to be registered very
- * late in startup, it will not get called if we suffer a failure *during*
- * startup.
+ * their own callbacks.
  *
  * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
  * via separate callbacks that execute before this one.  We don't combine the
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f3426b18cab0502493107c9a0025649305b352f0..bb0634463ed113463a65b911da6a86db11667093 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.280 2005/07/30 15:17:20 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.281 2005/08/11 21:11:47 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -672,7 +672,7 @@ static struct config_bool ConfigureNamesBool[] =
 			NULL
 		},
 		&pgstat_collect_resetonpmstart,
-		true, NULL, NULL
+		false, NULL, NULL
 	},
 	{
 		{"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
@@ -1160,6 +1160,24 @@ static struct config_int ConfigureNamesInt[] =
 		0, 0, 1000, NULL, NULL
 	},
 
+	{
+		{"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
+			gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
+			NULL
+		},
+		&autovacuum_vac_cost_delay,
+		-1, -1, 1000, NULL, NULL
+	},
+
+	{
+		{"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
+			gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
+			NULL
+		},
+		&autovacuum_vac_cost_limit,
+		-1, -1, 10000, NULL, NULL
+	},
+
 	{
 		{"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
 			gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 7eea5513c2b1ec5d63cbdf9cd8e563cd0a915e98..86f236910f85168c865c20e67a1cbaa0cc2f8b67 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -288,7 +288,7 @@
 #stats_command_string = off
 #stats_block_level = off
 #stats_row_level = off
-#stats_reset_on_server_start = on
+#stats_reset_on_server_start = off
 
 
 #---------------------------------------------------------------------------
@@ -301,6 +301,10 @@
 #autovacuum_analyze_threshold = 500	# min # of tuple updates before analyze
 #autovacuum_vacuum_scale_factor = 0.4	# fraction of rel size before vacuum
 #autovacuum_analyze_scale_factor = 0.2	# fraction of rel size before analyze
+#autovacuum_vacuum_cost_delay = -1  # default vacuum cost delay for autovac
+                                    # -1 means use vacuum_cost_delay
+#autovacuum_vacuum_cost_limit = -1  # default vacuum cost limit for autovac
+                                    # -1 means use vacuum_cost_limit
 
 
 #---------------------------------------------------------------------------
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 2ce578b3f4164e0dd44f3f5dcfc70f80b65f39c0..39df4d3eb21a529d33112f761fc06caa98670c6d 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.295 2005/08/01 20:31:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.296 2005/08/11 21:11:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200508011
+#define CATALOG_VERSION_NO	200508111
 
 #endif
diff --git a/src/include/catalog/pg_autovacuum.h b/src/include/catalog/pg_autovacuum.h
index b0bfc2049223fc4e0865ffda7511e06387f955fe..542668206a066228736d023b771898a5c0971ee6 100644
--- a/src/include/catalog/pg_autovacuum.h
+++ b/src/include/catalog/pg_autovacuum.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_autovacuum.h,v 1.1 2005/07/14 05:13:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_autovacuum.h,v 1.2 2005/08/11 21:11:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,6 +34,8 @@ CATALOG(pg_autovacuum,1248) BKI_WITHOUT_OIDS
 	float4		vac_scale_factor;  	/* reltuples scaling factor */
 	int4		anl_base_thresh;	/* base threshold value */
 	float4		anl_scale_factor;	/* reltuples scaling factor */
+	int4		vac_cost_delay;		/* vacuum cost-based delay */
+	int4		vac_cost_limit;		/* vacuum cost limit */
 } FormData_pg_autovacuum;
 
 /* ----------------
@@ -47,13 +49,15 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum;
  *		compiler constants for pg_autovacuum
  * ----------------
  */
-#define Natts_pg_autovacuum							6
+#define Natts_pg_autovacuum							8
 #define Anum_pg_autovacuum_vacrelid					1
 #define Anum_pg_autovacuum_enabled					2
 #define Anum_pg_autovacuum_vac_base_thresh			3
 #define Anum_pg_autovacuum_vac_scale_factor			4
 #define Anum_pg_autovacuum_anl_base_thresh			5
 #define Anum_pg_autovacuum_anl_scale_factor			6
+#define Anum_pg_autovacuum_vac_cost_delay			7
+#define Anum_pg_autovacuum_vac_cost_limit			8
 
 /* There are no preloaded tuples in pg_autovacuum.h */
 
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index 568aaf13c3d88d212f00ef0139378b2e6f71c2cb..380949811439d522737ef08a18595ff011919ddd 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -4,7 +4,7 @@
  *	  Interface to hba.c
  *
  *
- * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.39 2005/07/29 19:30:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.40 2005/08/11 21:11:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,6 +37,7 @@ extern void load_role(void);
 extern int	hba_getauthmethod(hbaPort *port);
 extern int	authident(hbaPort *port);
 extern bool	read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
-								  Oid *dbtablespace, TransactionId *dbfrozenxid);
+								  Oid *dbtablespace, TransactionId *dbfrozenxid,
+								  TransactionId *dbvacuumxid);
 
 #endif /* HBA_H */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index f8d5f02ea183249a39b8a39e9ea3c3073b4712c9..f747928a225fd1f9586b79987deb930ffa33f5c6 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
  *
  *	Copyright (c) 2001-2005, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.34 2005/07/29 19:30:09 tgl Exp $
+ *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.35 2005/08/11 21:11:49 tgl Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -367,6 +367,7 @@ extern bool pgstat_collect_blocklevel;
 extern void pgstat_init(void);
 extern int	pgstat_start(void);
 extern void pgstat_beterm(int pid);
+extern void pgstat_reset_all(void);
 
 #ifdef EXEC_BACKEND
 extern void PgstatBufferMain(int argc, char *argv[]);
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index 85667af1cc64a6bdcd8eb07ca903969f04419ab1..620a528f1bb90790aee8c33c347ad3f7a8051df3 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.1 2005/07/14 05:13:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.2 2005/08/11 21:11:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,8 @@ extern int		autovacuum_vac_thresh;
 extern double	autovacuum_vac_scale;
 extern int		autovacuum_anl_thresh;
 extern double	autovacuum_anl_scale;
+extern int		autovacuum_vac_cost_delay;
+extern int		autovacuum_vac_cost_limit;
 
 /* Status inquiry functions */
 extern bool AutoVacuumingActive(void);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 7886d66d7c954f65ef14936210c688c83d1b27dd..93b703c9293d048c556cca945e44596a64672442 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.76 2005/07/14 05:13:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.77 2005/08/11 21:11:50 tgl Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -59,6 +59,7 @@ extern void die(SIGNAL_ARGS);
 extern void quickdie(SIGNAL_ARGS);
 extern void authdie(SIGNAL_ARGS);
 extern void StatementCancelHandler(SIGNAL_ARGS);
+extern void FloatExceptionHandler(SIGNAL_ARGS);
 extern void prepare_for_client_read(void);
 extern void client_read_ended(void);
 extern int	PostgresMain(int argc, char *argv[], const char *username);