Separate the code to start a new worker into its own function. The code is

exactly the same, modulo whitespace.
This commit is contained in:
Alvaro Herrera 2007-03-23 21:45:17 +00:00
parent 6287eb7adc
commit a0abe87f1c
1 changed files with 100 additions and 85 deletions

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.36 2007/03/23 21:23:13 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.37 2007/03/23 21:45:17 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@ -118,6 +118,7 @@ static pid_t avworker_forkexec(void);
NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]);
static void do_start_worker(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,
@ -218,9 +219,6 @@ NON_EXEC_STATIC void
AutoVacLauncherMain(int argc, char *argv[])
{
sigjmp_buf local_sigjmp_buf;
List *dblist;
bool for_xid_wrap;
autovac_dbase *db;
MemoryContext avlauncher_cxt;
/* we are a postmaster subprocess now */
@ -358,8 +356,6 @@ AutoVacLauncherMain(int argc, char *argv[])
for (;;)
{
TransactionId xidForceLimit;
ListCell *cell;
int worker_pid;
/*
@ -407,86 +403,8 @@ AutoVacLauncherMain(int argc, char *argv[])
}
}
/* Get a list of databases */
dblist = autovac_get_database_list();
do_start_worker();
/*
* Determine the oldest datfrozenxid/relfrozenxid that we will allow
* to pass without forcing a vacuum. (This limit can be tightened for
* particular tables, but not loosened.)
*/
recentXid = ReadNewTransactionId();
xidForceLimit = recentXid - autovacuum_freeze_max_age;
/* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
if (xidForceLimit < FirstNormalTransactionId)
xidForceLimit -= FirstNormalTransactionId;
/*
* Choose a database to connect to. We pick the database that was least
* recently auto-vacuumed, or one that needs vacuuming to prevent Xid
* wraparound-related data loss. If any db at risk of wraparound is
* found, we pick the one with oldest datfrozenxid, independently of
* autovacuum times.
*
* Note that a database with no stats entry is not considered, except for
* Xid wraparound purposes. The theory is that if no one has ever
* connected to it since the stats were last initialized, it doesn't need
* vacuuming.
*
* XXX This could be improved if we had more info about whether it needs
* vacuuming before connecting to it. Perhaps look through the pgstats
* data for the database's tables? One idea is to keep track of the
* number of new and dead tuples per database in pgstats. However it
* isn't clear how to construct a metric that measures that and not cause
* starvation for less busy databases.
*/
db = NULL;
for_xid_wrap = false;
foreach(cell, dblist)
{
autovac_dbase *tmp = lfirst(cell);
/* Find pgstat entry if any */
tmp->entry = pgstat_fetch_stat_dbentry(tmp->oid);
/* Check to see if this one is at risk of wraparound */
if (TransactionIdPrecedes(tmp->frozenxid, xidForceLimit))
{
if (db == NULL ||
TransactionIdPrecedes(tmp->frozenxid, db->frozenxid))
db = tmp;
for_xid_wrap = true;
continue;
}
else if (for_xid_wrap)
continue; /* ignore not-at-risk DBs */
/*
* Otherwise, skip a database with no pgstat entry; it means it
* hasn't seen any activity.
*/
if (!tmp->entry)
continue;
/*
* Remember the db with oldest autovac time. (If we are here,
* both tmp->entry and db->entry must be non-null.)
*/
if (db == NULL ||
tmp->entry->last_autovac_time < db->entry->last_autovac_time)
db = tmp;
}
/* Found a database -- process it */
if (db != NULL)
{
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
AutoVacuumShmem->process_db = db->oid;
LWLockRelease(AutovacuumLock);
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER);
}
sleep:
/*
* in emergency mode, exit immediately so that the postmaster can
@ -512,6 +430,103 @@ sleep:
proc_exit(0); /* done */
}
/*
* do_start_worker
*
* Bare-bones procedure for starting an autovacuum worker from the launcher.
* It determines what database to work on, sets up shared memory stuff and
* signals postmaster to start the worker.
*/
static void
do_start_worker(void)
{
List *dblist;
bool for_xid_wrap;
autovac_dbase *db;
ListCell *cell;
TransactionId xidForceLimit;
/* Get a list of databases */
dblist = autovac_get_database_list();
/*
* Determine the oldest datfrozenxid/relfrozenxid that we will allow
* to pass without forcing a vacuum. (This limit can be tightened for
* particular tables, but not loosened.)
*/
recentXid = ReadNewTransactionId();
xidForceLimit = recentXid - autovacuum_freeze_max_age;
/* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
if (xidForceLimit < FirstNormalTransactionId)
xidForceLimit -= FirstNormalTransactionId;
/*
* Choose a database to connect to. We pick the database that was least
* recently auto-vacuumed, or one that needs vacuuming to prevent Xid
* wraparound-related data loss. If any db at risk of wraparound is
* found, we pick the one with oldest datfrozenxid, independently of
* autovacuum times.
*
* Note that a database with no stats entry is not considered, except for
* Xid wraparound purposes. The theory is that if no one has ever
* connected to it since the stats were last initialized, it doesn't need
* vacuuming.
*
* XXX This could be improved if we had more info about whether it needs
* vacuuming before connecting to it. Perhaps look through the pgstats
* data for the database's tables? One idea is to keep track of the
* number of new and dead tuples per database in pgstats. However it
* isn't clear how to construct a metric that measures that and not cause
* starvation for less busy databases.
*/
db = NULL;
for_xid_wrap = false;
foreach(cell, dblist)
{
autovac_dbase *tmp = lfirst(cell);
/* Find pgstat entry if any */
tmp->entry = pgstat_fetch_stat_dbentry(tmp->oid);
/* Check to see if this one is at risk of wraparound */
if (TransactionIdPrecedes(tmp->frozenxid, xidForceLimit))
{
if (db == NULL ||
TransactionIdPrecedes(tmp->frozenxid, db->frozenxid))
db = tmp;
for_xid_wrap = true;
continue;
}
else if (for_xid_wrap)
continue; /* ignore not-at-risk DBs */
/*
* Otherwise, skip a database with no pgstat entry; it means it
* hasn't seen any activity.
*/
if (!tmp->entry)
continue;
/*
* Remember the db with oldest autovac time. (If we are here,
* both tmp->entry and db->entry must be non-null.)
*/
if (db == NULL ||
tmp->entry->last_autovac_time < db->entry->last_autovac_time)
db = tmp;
}
/* Found a database -- process it */
if (db != NULL)
{
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
AutoVacuumShmem->process_db = db->oid;
LWLockRelease(AutovacuumLock);
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_WORKER);
}
}
/* SIGHUP: set flag to re-read config file at next convenient time */
static void
avl_sighup_handler(SIGNAL_ARGS)