1010 *
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.38 2007/03/23 21:57:10 alvherre Exp $
13+ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.39 2007/03/27 20:36:03 alvherre Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
@@ -85,22 +85,22 @@ static MemoryContext AutovacMemCxt;
8585/* struct to keep list of candidate databases for vacuum */
8686typedef struct autovac_dbase
8787{
88- Oid oid ;
89- char * name ;
90- TransactionId frozenxid ;
91- PgStat_StatDBEntry * entry ;
88+ Oid ad_datid ;
89+ char * ad_name ;
90+ TransactionId ad_frozenxid ;
91+ PgStat_StatDBEntry * ad_entry ;
9292}autovac_dbase ;
9393
94- /* struct to keep track of tables to vacuum and/or analyze */
94+ /* struct to keep track of tables to vacuum and/or analyze, after rechecking */
9595typedef struct autovac_table
9696{
97- Oid relid ;
98- Oid toastrelid ;
99- bool dovacuum ;
100- bool doanalyze ;
101- int freeze_min_age ;
102- int vacuum_cost_delay ;
103- int vacuum_cost_limit ;
97+ Oid at_relid ;
98+ Oid at_toastrelid ;
99+ bool at_dovacuum ;
100+ bool at_doanalyze ;
101+ int at_freeze_min_age ;
102+ int at_vacuum_cost_delay ;
103+ int at_vacuum_cost_limit ;
104104}autovac_table ;
105105
106106typedef struct
@@ -119,7 +119,7 @@ NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
119119NON_EXEC_STATIC void AutoVacLauncherMain (int argc ,char * argv []);
120120
121121static void do_start_worker (void );
122- static void do_autovacuum (PgStat_StatDBEntry * dbentry );
122+ static void do_autovacuum (Oid dbid );
123123static List * autovac_get_database_list (void );
124124static void test_rel_for_autovac (Oid relid ,PgStat_StatTabEntry * tabentry ,
125125Form_pg_class classForm ,
@@ -129,6 +129,9 @@ static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
129129static void autovacuum_do_vac_analyze (Oid relid ,bool dovacuum ,
130130bool doanalyze ,int freeze_min_age );
131131static HeapTuple get_pg_autovacuum_tuple_relid (Relation avRel ,Oid relid );
132+ static PgStat_StatTabEntry * get_pgstat_tabentry_relid (Oid relid ,bool isshared ,
133+ PgStat_StatDBEntry * shared ,
134+ PgStat_StatDBEntry * dbentry );
132135static void autovac_report_activity (VacuumStmt * vacstmt ,Oid relid );
133136static void avl_sighup_handler (SIGNAL_ARGS );
134137static void avlauncher_shutdown (SIGNAL_ARGS );
@@ -486,13 +489,13 @@ do_start_worker(void)
486489autovac_dbase * tmp = lfirst (cell );
487490
488491/* Find pgstat entry if any */
489- tmp -> entry = pgstat_fetch_stat_dbentry (tmp -> oid );
492+ tmp -> ad_entry = pgstat_fetch_stat_dbentry (tmp -> ad_datid );
490493
491494/* Check to see if this one is at risk of wraparound */
492- if (TransactionIdPrecedes (tmp -> frozenxid ,xidForceLimit ))
495+ if (TransactionIdPrecedes (tmp -> ad_frozenxid ,xidForceLimit ))
493496{
494497if (db == NULL ||
495- TransactionIdPrecedes (tmp -> frozenxid ,db -> frozenxid ))
498+ TransactionIdPrecedes (tmp -> ad_frozenxid ,db -> ad_frozenxid ))
496499db = tmp ;
497500for_xid_wrap = true;
498501continue ;
@@ -504,23 +507,23 @@ do_start_worker(void)
504507 * Otherwise, skip a database with no pgstat entry; it means it
505508 * hasn't seen any activity.
506509 */
507- if (!tmp -> entry )
510+ if (!tmp -> ad_entry )
508511continue ;
509512
510513/*
511514 * Remember the db with oldest autovac time. (If we are here,
512515 * both tmp->entry and db->entry must be non-null.)
513516 */
514517if (db == NULL ||
515- tmp -> entry -> last_autovac_time < db -> entry -> last_autovac_time )
518+ tmp -> ad_entry -> last_autovac_time < db -> ad_entry -> last_autovac_time )
516519db = tmp ;
517520}
518521
519522/* Found a database -- process it */
520523if (db != NULL )
521524{
522525LWLockAcquire (AutovacuumLock ,LW_EXCLUSIVE );
523- AutoVacuumShmem -> process_db = db -> oid ;
526+ AutoVacuumShmem -> process_db = db -> ad_datid ;
524527LWLockRelease (AutovacuumLock );
525528
526529SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_WORKER );
@@ -762,7 +765,6 @@ AutoVacWorkerMain(int argc, char *argv[])
762765if (OidIsValid (dbid ))
763766{
764767char * dbname ;
765- PgStat_StatDBEntry * dbentry ;
766768
767769/*
768770 * Report autovac startup to the stats collector. We deliberately do
@@ -795,8 +797,7 @@ AutoVacWorkerMain(int argc, char *argv[])
795797
796798/* And do an appropriate amount of work */
797799recentXid = ReadNewTransactionId ();
798- dbentry = pgstat_fetch_stat_dbentry (dbid );
799- do_autovacuum (dbentry );
800+ do_autovacuum (dbid );
800801}
801802
802803/*
@@ -838,17 +839,17 @@ autovac_get_database_list(void)
838839while (read_pg_database_line (db_file ,thisname ,& db_id ,
839840& db_tablespace ,& db_frozenxid ))
840841{
841- autovac_dbase * db ;
842+ autovac_dbase * avdb ;
842843
843- db = (autovac_dbase * )palloc (sizeof (autovac_dbase ));
844+ avdb = (autovac_dbase * )palloc (sizeof (autovac_dbase ));
844845
845- db -> oid = db_id ;
846- db -> name = pstrdup (thisname );
847- db -> frozenxid = db_frozenxid ;
846+ avdb -> ad_datid = db_id ;
847+ avdb -> ad_name = pstrdup (thisname );
848+ avdb -> ad_frozenxid = db_frozenxid ;
848849/* this gets set later: */
849- db -> entry = NULL ;
850+ avdb -> ad_entry = NULL ;
850851
851- dblist = lappend (dblist ,db );
852+ dblist = lappend (dblist ,avdb );
852853}
853854
854855FreeFile (db_file );
@@ -860,15 +861,11 @@ autovac_get_database_list(void)
860861/*
861862 * Process a database table-by-table
862863 *
863- * dbentry is either a pointer to the database entry in the stats databases
864- * hash table, or NULL if we couldn't find any entry (the latter case occurs
865- * only if we are forcing a vacuum for anti-wrap purposes).
866- *
867864 * Note that CHECK_FOR_INTERRUPTS is supposed to be used in certain spots in
868865 * order not to ignore shutdown commands for too long.
869866 */
870867static void
871- do_autovacuum (PgStat_StatDBEntry * dbentry )
868+ do_autovacuum (Oid dbid )
872869{
873870Relation classRel ,
874871avRel ;
@@ -879,6 +876,13 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
879876List * toast_table_ids = NIL ;
880877ListCell * cell ;
881878PgStat_StatDBEntry * shared ;
879+ PgStat_StatDBEntry * dbentry ;
880+
881+ /*
882+ * may be NULL if we couldn't find an entry (only happens if we
883+ * are forcing a vacuum for anti-wrap purposes).
884+ */
885+ dbentry = pgstat_fetch_stat_dbentry (dbid );
882886
883887/* Start a transaction so our commands have one to play into. */
884888StartTransactionCommand ();
@@ -968,18 +972,12 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
968972
969973/* Fetch the pg_autovacuum tuple for the relation, if any */
970974avTup = get_pg_autovacuum_tuple_relid (avRel ,relid );
971-
972975if (HeapTupleIsValid (avTup ))
973976avForm = (Form_pg_autovacuum )GETSTRUCT (avTup );
974977
975- if (classForm -> relisshared && PointerIsValid (shared ))
976- tabentry = hash_search (shared -> tables ,& relid ,
977- HASH_FIND ,NULL );
978- else if (PointerIsValid (dbentry ))
979- tabentry = hash_search (dbentry -> tables ,& relid ,
980- HASH_FIND ,NULL );
981- else
982- tabentry = NULL ;
978+ /* Fetch the pgstat entry for this table */
979+ tabentry = get_pgstat_tabentry_relid (relid ,classForm -> relisshared ,
980+ shared ,dbentry );
983981
984982test_rel_for_autovac (relid ,tabentry ,classForm ,avForm ,
985983& vacuum_tables ,& toast_table_ids );
@@ -1005,26 +1003,26 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
10051003 * Check to see if we need to force vacuuming of this table because
10061004 * its toast table needs it.
10071005 */
1008- if (OidIsValid (tab -> toastrelid )&& !tab -> dovacuum &&
1009- list_member_oid (toast_table_ids ,tab -> toastrelid ))
1006+ if (OidIsValid (tab -> at_toastrelid )&& !tab -> at_dovacuum &&
1007+ list_member_oid (toast_table_ids ,tab -> at_toastrelid ))
10101008{
1011- tab -> dovacuum = true;
1009+ tab -> at_dovacuum = true;
10121010elog (DEBUG2 ,"autovac: VACUUM %u because of TOAST table" ,
1013- tab -> relid );
1011+ tab -> at_relid );
10141012}
10151013
10161014/* Otherwise, ignore table if it needs no work */
1017- if (!tab -> dovacuum && !tab -> doanalyze )
1015+ if (!tab -> at_dovacuum && !tab -> at_doanalyze )
10181016continue ;
10191017
10201018/* Set the vacuum cost parameters for this table */
1021- VacuumCostDelay = tab -> vacuum_cost_delay ;
1022- VacuumCostLimit = tab -> vacuum_cost_limit ;
1019+ VacuumCostDelay = tab -> at_vacuum_cost_delay ;
1020+ VacuumCostLimit = tab -> at_vacuum_cost_limit ;
10231021
1024- autovacuum_do_vac_analyze (tab -> relid ,
1025- tab -> dovacuum ,
1026- tab -> doanalyze ,
1027- tab -> freeze_min_age );
1022+ autovacuum_do_vac_analyze (tab -> at_relid ,
1023+ tab -> at_dovacuum ,
1024+ tab -> at_doanalyze ,
1025+ tab -> at_freeze_min_age );
10281026}
10291027
10301028/*
@@ -1066,6 +1064,30 @@ get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid)
10661064return avTup ;
10671065}
10681066
1067+ /*
1068+ * get_pgstat_tabentry_relid
1069+ *
1070+ * Fetch the pgstat entry of a table, either local to a database or shared.
1071+ */
1072+ static PgStat_StatTabEntry *
1073+ get_pgstat_tabentry_relid (Oid relid ,bool isshared ,PgStat_StatDBEntry * shared ,
1074+ PgStat_StatDBEntry * dbentry )
1075+ {
1076+ PgStat_StatTabEntry * tabentry = NULL ;
1077+
1078+ if (isshared )
1079+ {
1080+ if (PointerIsValid (shared ))
1081+ tabentry = hash_search (shared -> tables ,& relid ,
1082+ HASH_FIND ,NULL );
1083+ }
1084+ else if (PointerIsValid (dbentry ))
1085+ tabentry = hash_search (dbentry -> tables ,& relid ,
1086+ HASH_FIND ,NULL );
1087+
1088+ return tabentry ;
1089+ }
1090+
10691091/*
10701092 * test_rel_for_autovac
10711093 *
@@ -1246,13 +1268,13 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
12461268autovac_table * tab ;
12471269
12481270tab = (autovac_table * )palloc (sizeof (autovac_table ));
1249- tab -> relid = relid ;
1250- tab -> toastrelid = classForm -> reltoastrelid ;
1251- tab -> dovacuum = dovacuum ;
1252- tab -> doanalyze = doanalyze ;
1253- tab -> freeze_min_age = freeze_min_age ;
1254- tab -> vacuum_cost_limit = vac_cost_limit ;
1255- tab -> vacuum_cost_delay = vac_cost_delay ;
1271+ tab -> at_relid = relid ;
1272+ tab -> at_toastrelid = classForm -> reltoastrelid ;
1273+ tab -> at_dovacuum = dovacuum ;
1274+ tab -> at_doanalyze = doanalyze ;
1275+ tab -> at_freeze_min_age = freeze_min_age ;
1276+ tab -> at_vacuum_cost_limit = vac_cost_limit ;
1277+ tab -> at_vacuum_cost_delay = vac_cost_delay ;
12561278
12571279* vacuum_tables = lappend (* vacuum_tables ,tab );
12581280}