*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.61 2007/09/24 04:12:01 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.62 2007/10/24 19:08:25 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
* wi_links entry into free list or running list
* wi_dboid OID of the database this worker is supposed to work on
* wi_tableoid OID of the table currently being vacuumed
- * wi_workerpid PID of the running worker, 0 if not yet started
+ * wi_proc pointer to PGPROC of the running worker, NULL if not started
* wi_launchtime Time at which this worker was launched
* wi_cost_* Vacuum cost-based delay parameters current in this worker
*
SHM_QUEUE wi_links;
Oid wi_dboid;
Oid wi_tableoid;
- int wi_workerpid;
+ PGPROC *wi_proc;
TimestampTz wi_launchtime;
int wi_cost_delay;
int wi_cost_limit;
/* Identify myself via ps */
init_ps_display("autovacuum launcher process", "", "", "");
+ if (PostAuthDelay)
+ pg_usleep(PostAuthDelay * 1000000L);
+
SetProcessingMode(InitProcessing);
/*
worker = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
worker->wi_dboid = InvalidOid;
worker->wi_tableoid = InvalidOid;
- worker->wi_workerpid = 0;
+ worker->wi_proc = NULL;
worker->wi_launchtime = 0;
worker->wi_links.next = AutoVacuumShmem->av_freeWorkers;
AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(worker);
AutoVacuumShmem->av_freeWorkers = worker->wi_links.next;
worker->wi_dboid = avdb->adw_datid;
- worker->wi_workerpid = 0;
+ worker->wi_proc = NULL;
worker->wi_launchtime = GetCurrentTimestamp();
AutoVacuumShmem->av_startingWorker = sworker;
/* Identify myself via ps */
init_ps_display("autovacuum worker process", "", "", "");
+ if (PostAuthDelay)
+ pg_usleep(PostAuthDelay * 1000000L);
+
SetProcessingMode(InitProcessing);
/*
{
MyWorkerInfo = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
dbid = MyWorkerInfo->wi_dboid;
- MyWorkerInfo->wi_workerpid = MyProcPid;
+ MyWorkerInfo->wi_proc = MyProc;
/* insert into the running list */
SHMQueueInsertBefore(&AutoVacuumShmem->av_runningWorkers,
MyWorkerInfo->wi_links.next = AutoVacuumShmem->av_freeWorkers;
MyWorkerInfo->wi_dboid = InvalidOid;
MyWorkerInfo->wi_tableoid = InvalidOid;
- MyWorkerInfo->wi_workerpid = 0;
+ MyWorkerInfo->wi_proc = NULL;
MyWorkerInfo->wi_launchtime = 0;
MyWorkerInfo->wi_cost_delay = 0;
MyWorkerInfo->wi_cost_limit = 0;
offsetof(WorkerInfoData, wi_links));
while (worker)
{
- if (worker->wi_workerpid != 0 &&
+ if (worker->wi_proc != NULL &&
worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
cost_total +=
(double) worker->wi_cost_limit_base / worker->wi_cost_delay;
offsetof(WorkerInfoData, wi_links));
while (worker)
{
- if (worker->wi_workerpid != 0 &&
+ if (worker->wi_proc != NULL &&
worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
{
int limit = (int)
worker->wi_cost_limit = Max(Min(limit, worker->wi_cost_limit_base), 1);
elog(DEBUG2, "autovac_balance_cost(pid=%u db=%u, rel=%u, cost_limit=%d, cost_delay=%d)",
- worker->wi_workerpid, worker->wi_dboid,
+ worker->wi_proc->pid, worker->wi_dboid,
worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_delay);
}
VacuumCostDelay = tab->at_vacuum_cost_delay;
VacuumCostLimit = tab->at_vacuum_cost_limit;
- /*
- * Advertise my cost delay parameters for the balancing algorithm, and
- * do a balance
- */
+ /* Last fixups before actually starting to work */
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
+
+ /* advertise my cost delay parameters for the balancing algorithm */
MyWorkerInfo->wi_cost_delay = tab->at_vacuum_cost_delay;
MyWorkerInfo->wi_cost_limit = tab->at_vacuum_cost_limit;
MyWorkerInfo->wi_cost_limit_base = tab->at_vacuum_cost_limit;
+
+ /* do a balance */
autovac_balance_cost();
+
+ /* done */
LWLockRelease(AutovacuumLock);
/* clean up memory before each iteration */
MemoryContextResetAndDeleteChildren(PortalContext);
/*
- * We will abort vacuuming the current table if we are interrupted, and
- * continue with the next one in schedule; but if anything else
- * happens, we will do our usual error handling which is to cause the
- * worker process to exit.
+ * We will abort vacuuming the current table if something errors out,
+ * and continue with the next one in schedule; in particular, this
+ * happens if we are interrupted with SIGINT.
*/
PG_TRY();
{
}
PG_CATCH();
{
- ErrorData *errdata;
-
- MemoryContextSwitchTo(TopTransactionContext);
- errdata = CopyErrorData();
-
/*
- * If we errored out due to a cancel request, abort and restart the
- * transaction and go to the next table. Otherwise rethrow the
- * error so that the outermost handler deals with it.
+ * Abort the transaction, start a new one, and proceed with the
+ * next table in our list.
*/
- if (errdata->sqlerrcode == ERRCODE_QUERY_CANCELED)
- {
- HOLD_INTERRUPTS();
- elog(LOG, "cancelling autovacuum of table \"%s.%s.%s\"",
- get_database_name(MyDatabaseId),
- get_namespace_name(get_rel_namespace(tab->at_relid)),
- get_rel_name(tab->at_relid));
-
- AbortOutOfAnyTransaction();
- FlushErrorState();
- MemoryContextResetAndDeleteChildren(PortalContext);
-
- /* restart our transaction for the following operations */
- StartTransactionCommand();
- RESUME_INTERRUPTS();
- }
+ HOLD_INTERRUPTS();
+ if (tab->at_dovacuum)
+ errcontext("automatic vacuum of table \"%s.%s.%s\"",
+ get_database_name(MyDatabaseId),
+ get_namespace_name(get_rel_namespace(tab->at_relid)),
+ get_rel_name(tab->at_relid));
else
- PG_RE_THROW();
+ errcontext("automatic analyze of table \"%s.%s.%s\"",
+ get_database_name(MyDatabaseId),
+ get_namespace_name(get_rel_namespace(tab->at_relid)),
+ get_rel_name(tab->at_relid));
+ EmitErrorReport();
+
+ AbortOutOfAnyTransaction();
+ FlushErrorState();
+ MemoryContextResetAndDeleteChildren(PortalContext);
+
+ /* restart our transaction for the following operations */
+ StartTransactionCommand();
+ RESUME_INTERRUPTS();
}
PG_END_TRY();
/* be tidy */
pfree(tab);
+
+ /* remove my info from shared memory */
+ LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
+ MyWorkerInfo->wi_tableoid = InvalidOid;
+ LWLockRelease(AutovacuumLock);
}
/*