diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index d8ec4f9f65..f938a27bb9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ @@ -1197,6 +1197,20 @@ Multiplier for reltuples to add to anl_base_thresh + + + vac_cost_delay + integer + + Custom vacuum_cost_delay parameter + + + + vac_cost_limit + integer + + Custom vacuum_cost_limit parameter + @@ -1217,7 +1231,11 @@ Any of the numerical fields can contain -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 + vac_cost_delay variable inherits its default value from the + autovacuum_vacuum_cost_delay configuration parameter, + or from vacuum_cost_delay if the former is set to a negative + value. The same applies to vac_cost_limit. diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 87a9763963..060cd91ea1 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -3296,7 +3296,7 @@ SELECT * FROM parent WHERE key = 2400; If on, collected statistics are zeroed out whenever the server is restarted. If off, statistics are accumulated across server - restarts. The default is on. This option can only + restarts. The default is off. This option can only be set at server start. @@ -3424,6 +3424,40 @@ SELECT * FROM parent WHERE key = 2400; + + autovacuum_vacuum_cost_delay (integer) + + autovacuum_vacuum_cost_delay configuration parameter + + + + Specifies the cost delay value that will be used in automatic + VACUUM operations. If -1 is specified (which is the + default), the regular + value will be used. + This setting can be overridden for individual tables by entries in + pg_autovacuum. + + + + + + autovacuum_vacuum_cost_limit (integer) + + autovacuum_vacuum_cost_limit configuration parameter + + + + Specifies the cost limit value that will be used in automatic + VACUUM operations. If -1 is specified (which is the + default), the regular + value will be used. + This setting can be overridden for individual tables by entries in + pg_autovacuum. + + + + diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index d1e36652b2..ae57ec0231 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 717b398f89..f565442ac6 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 10eb9b6da8..3b3093727f 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. + * 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 * - * 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. - * - * 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) + /* The database hash where pgstat keeps shared relations */ + shared = pgstat_fetch_stat_dbentry(InvalidOid); + + classRel = heap_open(RelationRelationId, AccessShareLock); + avRel = heap_open(AutovacuumRelationId, AccessShareLock); + + relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL); + + /* Scan pg_class looking for tables to vacuum */ + while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) { - 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); + 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; - classRel = heap_open(RelationRelationId, AccessShareLock); - avRel = heap_open(AutovacuumRelationId, AccessShareLock); - - relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL); - - /* 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; - - /* - * Skip temp tables (i.e. those in temp namespaces). We cannot - * safely process other backends' temp tables. - */ - if (isTempNamespace(classForm->relnamespace)) - continue; - - relid = HeapTupleGetOid(tuple); - - /* See if we have a pg_autovacuum entry for this relation. */ - ScanKeyInit(&entry[0], - Anum_pg_autovacuum_vacrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid)); - - avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true, - SnapshotNow, 1, entry); - - avTup = systable_getnext(avScan); - - if (HeapTupleIsValid(avTup)) - avForm = (Form_pg_autovacuum) GETSTRUCT(avTup); - - if (classForm->relisshared && PointerIsValid(shared)) - tabentry = hash_search(shared->tables, &relid, - HASH_FIND, NULL); - else - tabentry = hash_search(dbentry->tables, &relid, - HASH_FIND, NULL); - - test_rel_for_autovac(relid, tabentry, classForm, avForm, - &vacuum_tables, &analyze_tables); - - systable_endscan(avScan); - } - - heap_endscan(relScan); - heap_close(avRel, AccessShareLock); - heap_close(classRel, AccessShareLock); - - CHECK_FOR_INTERRUPTS(); + /* Skip non-table entries. */ + /* XXX possibly allow RELKIND_TOASTVALUE entries here too? */ + if (classForm->relkind != RELKIND_RELATION) + continue; /* - * Perform operations on collected tables. + * Skip temp tables (i.e. those in temp namespaces). We cannot + * safely process other backends' temp tables. */ + if (isTempNamespace(classForm->relnamespace)) + continue; - if (analyze_tables) - autovacuum_do_vac_analyze(analyze_tables, false); + relid = HeapTupleGetOid(tuple); + + /* See if we have a pg_autovacuum entry for this relation. */ + ScanKeyInit(&entry[0], + Anum_pg_autovacuum_vacrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + + avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true, + SnapshotNow, 1, entry); + + avTup = systable_getnext(avScan); + + if (HeapTupleIsValid(avTup)) + avForm = (Form_pg_autovacuum) GETSTRUCT(avTup); + + if (classForm->relisshared && PointerIsValid(shared)) + tabentry = hash_search(shared->tables, &relid, + HASH_FIND, NULL); + else + tabentry = hash_search(dbentry->tables, &relid, + HASH_FIND, NULL); + + test_rel_for_autovac(relid, tabentry, classForm, avForm, + &vacuum_tables); + + systable_endscan(avScan); + } + + heap_endscan(relScan); + heap_close(avRel, AccessShareLock); + heap_close(classRel, AccessShareLock); + + /* + * 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; + 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) ? - autovacuum_anl_scale : avForm->anl_scale_factor; - anl_base_thresh = (avForm->anl_base_thresh < 0) ? - autovacuum_anl_thresh : avForm->anl_base_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 00ed7b837d..bbb1027fa2 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 091fbeed0b..110b5816c4 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 5025ab8f56..aa0da207a3 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 7087a9887d..7d9d2e6cb2 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 058872a73f..73fedbdd47 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 #include +#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 f3426b18ca..bb0634463e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.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 7eea5513c2..86f236910f 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 2ce578b3f4..39df4d3eb2 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 b0bfc20492..542668206a 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 568aaf13c3..3809498114 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 f8d5f02ea1..f747928a22 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 85667af1cc..620a528f1b 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 7886d66d7c..93b703c929 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);