In the spirit of incremental improvement, here is a patch that turns the
couple of bools in PGPROC into a bitmask, and associated fallout.
This patch also contains a change to make a cancelled autovacuum
continue with the schedule (indeed to continue with the schedule on any
error), rather than aborting completely.
My idea is to add a flag for "analyze" and another for "is for xid
wraparound", and to build on that for the cancel-autovac-on-deadlock-
checker project, as submitted by Simon.
--
Alvaro Herrera Valdivia, Chile ICBM: S 39º 49' 18.1", W 73º 13' 56.4"
"El sudor es la mejor cura para un pensamiento enfermo" (Bardia)
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.36
diff -c -p -r1.36 twophase.c
*** src/backend/access/transam/twophase.c 21 Sep 2007 16:32:19 -0000 1.36
--- src/backend/access/transam/twophase.c 23 Oct 2007 20:22:51 -0000
*************** MarkAsPreparing(TransactionId xid, const
*** 283,290 ****
gxact->proc.databaseId = databaseid;
gxact->proc.roleId = owner;
gxact->proc.inCommit = false;
! gxact->proc.inVacuum = false;
! gxact->proc.isAutovacuum = false;
gxact->proc.lwWaiting = false;
gxact->proc.lwExclusive = false;
gxact->proc.lwWaitLink = NULL;
--- 283,289 ----
gxact->proc.databaseId = databaseid;
gxact->proc.roleId = owner;
gxact->proc.inCommit = false;
! gxact->proc.vacuumFlags = 0;
gxact->proc.lwWaiting = false;
gxact->proc.lwExclusive = false;
gxact->proc.lwWaitLink = NULL;
Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.359
diff -c -p -r1.359 vacuum.c
*** src/backend/commands/vacuum.c 20 Sep 2007 17:56:31 -0000 1.359
--- src/backend/commands/vacuum.c 23 Oct 2007 20:26:39 -0000
*************** vacuum_set_xid_limits(int freeze_min_age
*** 660,668 ****
* fixed-size never-null columns, but these are.
*
* Another reason for doing it this way is that when we are in a lazy
! * VACUUM and have inVacuum set, we mustn't do any updates --- somebody
! * vacuuming pg_class might think they could delete a tuple marked with
! * xmin = our xid.
*
* This routine is shared by full VACUUM, lazy VACUUM, and stand-alone
* ANALYZE.
--- 660,668 ----
* fixed-size never-null columns, but these are.
*
* Another reason for doing it this way is that when we are in a lazy
! * VACUUM and have PROC_IN_VACUUM set, we mustn't do any updates ---
! * somebody vacuuming pg_class might think they could delete a tuple
! * marked with xmin = our xid.
*
* This routine is shared by full VACUUM, lazy VACUUM, and stand-alone
* ANALYZE.
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 987,995 ****
* During a lazy VACUUM we do not run any user-supplied functions, and
* so it should be safe to not create a transaction snapshot.
*
! * We can furthermore set the inVacuum flag, which lets other
* concurrent VACUUMs know that they can ignore this one while
! * determining their OldestXmin. (The reason we don't set inVacuum
* during a full VACUUM is exactly that we may have to run user-
* defined functions for functional indexes, and we want to make sure
* that if they use the snapshot set above, any tuples it requires
--- 987,995 ----
* During a lazy VACUUM we do not run any user-supplied functions, and
* so it should be safe to not create a transaction snapshot.
*
! * We can furthermore set the PROC_IN_VACUUM flag, which lets other
* concurrent VACUUMs know that they can ignore this one while
! * determining their OldestXmin. (The reason we don't set it
* during a full VACUUM is exactly that we may have to run user-
* defined functions for functional indexes, and we want to make sure
* that if they use the snapshot set above, any tuples it requires
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 997,1008 ****
* depends on the contents of other tables is arguably broken, but we
* won't break it here by violating transaction semantics.)
*
! * Note: the inVacuum flag remains set until CommitTransaction or
* AbortTransaction. We don't want to clear it until we reset
* MyProc->xid/xmin, else OldestXmin might appear to go backwards,
* which is probably Not Good.
*/
! MyProc->inVacuum = true;
}
/*
--- 997,1008 ----
* depends on the contents of other tables is arguably broken, but we
* won't break it here by violating transaction semantics.)
*
! * Note: this flag remains set until CommitTransaction or
* AbortTransaction. We don't want to clear it until we reset
* MyProc->xid/xmin, else OldestXmin might appear to go backwards,
* which is probably Not Good.
*/
! MyProc->vacuumFlags |= PROC_IN_VACUUM;
}
/*
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.61
diff -c -p -r1.61 autovacuum.c
*** src/backend/postmaster/autovacuum.c 24 Sep 2007 04:12:01 -0000 1.61
--- src/backend/postmaster/autovacuum.c 23 Oct 2007 20:49:24 -0000
*************** typedef struct autovac_table
*** 182,188 ****
* 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_launchtime Time at which this worker was launched
* wi_cost_* Vacuum cost-based delay parameters current in this worker
*
--- 182,188 ----
* 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_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
*
*************** typedef struct WorkerInfoData
*** 196,202 ****
SHM_QUEUE wi_links;
Oid wi_dboid;
Oid wi_tableoid;
! int wi_workerpid;
TimestampTz wi_launchtime;
int wi_cost_delay;
int wi_cost_limit;
--- 196,202 ----
SHM_QUEUE wi_links;
Oid wi_dboid;
Oid wi_tableoid;
! PGPROC *wi_proc;
TimestampTz wi_launchtime;
int wi_cost_delay;
int wi_cost_limit;
*************** AutoVacLauncherMain(int argc, char *argv
*** 694,700 ****
worker = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
worker->wi_dboid = InvalidOid;
worker->wi_tableoid = InvalidOid;
! worker->wi_workerpid = 0;
worker->wi_launchtime = 0;
worker->wi_links.next = AutoVacuumShmem->av_freeWorkers;
AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(worker);
--- 694,700 ----
worker = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
worker->wi_dboid = InvalidOid;
worker->wi_tableoid = InvalidOid;
! worker->wi_proc = NULL;
worker->wi_launchtime = 0;
worker->wi_links.next = AutoVacuumShmem->av_freeWorkers;
AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(worker);
*************** do_start_worker(void)
*** 1198,1204 ****
AutoVacuumShmem->av_freeWorkers = worker->wi_links.next;
worker->wi_dboid = avdb->adw_datid;
! worker->wi_workerpid = 0;
worker->wi_launchtime = GetCurrentTimestamp();
AutoVacuumShmem->av_startingWorker = sworker;
--- 1198,1204 ----
AutoVacuumShmem->av_freeWorkers = worker->wi_links.next;
worker->wi_dboid = avdb->adw_datid;
! worker->wi_proc = NULL;
worker->wi_launchtime = GetCurrentTimestamp();
AutoVacuumShmem->av_startingWorker = sworker;
*************** AutoVacWorkerMain(int argc, char *argv[]
*** 1542,1548 ****
{
MyWorkerInfo = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
dbid = MyWorkerInfo->wi_dboid;
! MyWorkerInfo->wi_workerpid = MyProcPid;
/* insert into the running list */
SHMQueueInsertBefore(&AutoVacuumShmem->av_runningWorkers,
--- 1542,1548 ----
{
MyWorkerInfo = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker);
dbid = MyWorkerInfo->wi_dboid;
! MyWorkerInfo->wi_proc = MyProc;
/* insert into the running list */
SHMQueueInsertBefore(&AutoVacuumShmem->av_runningWorkers,
*************** FreeWorkerInfo(int code, Datum arg)
*** 1637,1643 ****
MyWorkerInfo->wi_links.next = AutoVacuumShmem->av_freeWorkers;
MyWorkerInfo->wi_dboid = InvalidOid;
MyWorkerInfo->wi_tableoid = InvalidOid;
! MyWorkerInfo->wi_workerpid = 0;
MyWorkerInfo->wi_launchtime = 0;
MyWorkerInfo->wi_cost_delay = 0;
MyWorkerInfo->wi_cost_limit = 0;
--- 1637,1643 ----
MyWorkerInfo->wi_links.next = AutoVacuumShmem->av_freeWorkers;
MyWorkerInfo->wi_dboid = InvalidOid;
MyWorkerInfo->wi_tableoid = InvalidOid;
! MyWorkerInfo->wi_proc = NULL;
MyWorkerInfo->wi_launchtime = 0;
MyWorkerInfo->wi_cost_delay = 0;
MyWorkerInfo->wi_cost_limit = 0;
*************** autovac_balance_cost(void)
*** 1701,1707 ****
offsetof(WorkerInfoData, wi_links));
while (worker)
{
! if (worker->wi_workerpid != 0 &&
worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
cost_total +=
(double) worker->wi_cost_limit_base / worker->wi_cost_delay;
--- 1701,1707 ----
offsetof(WorkerInfoData, wi_links));
while (worker)
{
! 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;
*************** autovac_balance_cost(void)
*** 1724,1730 ****
offsetof(WorkerInfoData, wi_links));
while (worker)
{
! if (worker->wi_workerpid != 0 &&
worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
{
int limit = (int)
--- 1724,1730 ----
offsetof(WorkerInfoData, wi_links));
while (worker)
{
! if (worker->wi_proc != NULL &&
worker->wi_cost_limit_base > 0 && worker->wi_cost_delay > 0)
{
int limit = (int)
*************** autovac_balance_cost(void)
*** 1737,1743 ****
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_tableoid, worker->wi_cost_limit, worker->wi_cost_delay);
}
--- 1737,1743 ----
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_proc->pid, worker->wi_dboid,
worker->wi_tableoid, worker->wi_cost_limit, worker->wi_cost_delay);
}
*************** next_worker:
*** 2062,2086 ****
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
! */
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
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;
autovac_balance_cost();
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.
*/
PG_TRY();
{
--- 2062,2088 ----
VacuumCostDelay = tab->at_vacuum_cost_delay;
VacuumCostLimit = tab->at_vacuum_cost_limit;
! /* 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 something errors out,
! * and continue with the next one in schedule; in particular, this
! * happens if we are interrupted with SIGINT.
*/
PG_TRY();
{
*************** next_worker:
*** 2094,2132 ****
}
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.
*/
! 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();
! }
else
! PG_RE_THROW();
}
PG_END_TRY();
/* be tidy */
pfree(tab);
}
/*
--- 2096,2135 ----
}
PG_CATCH();
{
/*
! * Abort the transaction, start a new one, and proceed with the
! * next table in our list.
*/
! 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
! 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);
}
/*
Index: src/backend/storage/ipc/procarray.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.35
diff -c -p -r1.35 procarray.c
*** src/backend/storage/ipc/procarray.c 23 Sep 2007 18:50:38 -0000 1.35
--- src/backend/storage/ipc/procarray.c 23 Oct 2007 20:31:13 -0000
*************** ProcArrayEndTransaction(PGPROC *proc, Tr
*** 242,248 ****
proc->xid = InvalidTransactionId;
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->inVacuum = false; /* must be cleared with xid/xmin */
proc->inCommit = false; /* be sure this is cleared in abort */
/* Clear the subtransaction-XID cache too while holding the lock */
--- 242,248 ----
proc->xid = InvalidTransactionId;
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->vacuumFlags &= ~PROC_IN_VACUUM; /* must be cleared with xid/xmin */
proc->inCommit = false; /* be sure this is cleared in abort */
/* Clear the subtransaction-XID cache too while holding the lock */
*************** ProcArrayEndTransaction(PGPROC *proc, Tr
*** 267,273 ****
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->inVacuum = false; /* must be cleared with xid/xmin */
proc->inCommit = false; /* be sure this is cleared in abort */
Assert(proc->subxids.nxids == 0);
--- 267,273 ----
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->vacuumFlags &= ~PROC_IN_VACUUM; /* must be cleared with xid/xmin */
proc->inCommit = false; /* be sure this is cleared in abort */
Assert(proc->subxids.nxids == 0);
*************** ProcArrayClearTransaction(PGPROC *proc)
*** 296,302 ****
proc->xid = InvalidTransactionId;
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->inVacuum = false; /* redundant, but just in case */
proc->inCommit = false; /* ditto */
/* Clear the subtransaction-XID cache too */
--- 296,302 ----
proc->xid = InvalidTransactionId;
proc->lxid = InvalidLocalTransactionId;
proc->xmin = InvalidTransactionId;
! proc->vacuumFlags &= ~PROC_IN_VACUUM; /* redundant, but just in case */
proc->inCommit = false; /* ditto */
/* Clear the subtransaction-XID cache too */
*************** TransactionIdIsActive(TransactionId xid)
*** 546,552 ****
* If allDbs is TRUE then all backends are considered; if allDbs is FALSE
* then only backends running in my own database are considered.
*
! * If ignoreVacuum is TRUE then backends with inVacuum set are ignored.
*
* This is used by VACUUM to decide which deleted tuples must be preserved
* in a table. allDbs = TRUE is needed for shared relations, but allDbs =
--- 546,553 ----
* If allDbs is TRUE then all backends are considered; if allDbs is FALSE
* then only backends running in my own database are considered.
*
! * If ignoreVacuum is TRUE then backends with the PROC_IN_VACUUM flag set are
! * ignored.
*
* This is used by VACUUM to decide which deleted tuples must be preserved
* in a table. allDbs = TRUE is needed for shared relations, but allDbs =
*************** GetOldestXmin(bool allDbs, bool ignoreVa
*** 586,592 ****
{
volatile PGPROC *proc = arrayP->procs[index];
! if (ignoreVacuum && proc->inVacuum)
continue;
if (allDbs || proc->databaseId == MyDatabaseId)
--- 587,593 ----
{
volatile PGPROC *proc = arrayP->procs[index];
! if (ignoreVacuum && (proc->vacuumFlags & PROC_IN_VACUUM))
continue;
if (allDbs || proc->databaseId == MyDatabaseId)
*************** GetSnapshotData(Snapshot snapshot, bool
*** 723,729 ****
TransactionId xid;
/* Ignore procs running LAZY VACUUM */
! if (proc->inVacuum)
continue;
/* Update globalxmin to be the smallest valid xmin */
--- 724,730 ----
TransactionId xid;
/* Ignore procs running LAZY VACUUM */
! if (proc->vacuumFlags & PROC_IN_VACUUM)
continue;
/* Update globalxmin to be the smallest valid xmin */
*************** CheckOtherDBBackends(Oid databaseId)
*** 1193,1199 ****
found = true;
! if (proc->isAutovacuum)
{
/* an autovacuum --- send it SIGTERM before sleeping */
int autopid = proc->pid;
--- 1194,1200 ----
found = true;
! if (proc->vacuumFlags & PROC_IS_AUTOVACUUM)
{
/* an autovacuum --- send it SIGTERM before sleeping */
int autopid = proc->pid;
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.194
diff -c -p -r1.194 proc.c
*** src/backend/storage/lmgr/proc.c 8 Sep 2007 20:31:15 -0000 1.194
--- src/backend/storage/lmgr/proc.c 23 Oct 2007 20:25:08 -0000
*************** InitProcess(void)
*** 291,298 ****
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
! MyProc->inVacuum = false;
! MyProc->isAutovacuum = IsAutoVacuumWorkerProcess();
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
--- 291,298 ----
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
! if (IsAutoVacuumWorkerProcess())
! MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
*************** InitAuxiliaryProcess(void)
*** 429,436 ****
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
! MyProc->inVacuum = false;
! MyProc->isAutovacuum = IsAutoVacuumLauncherProcess(); /* is this needed? */
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
--- 429,436 ----
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
! /* we don't set the "is autovacuum" flag in the launcher */
! MyProc->vacuumFlags = 0;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
Index: src/include/storage/proc.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/storage/proc.h,v
retrieving revision 1.100
diff -c -p -r1.100 proc.h
*** src/include/storage/proc.h 5 Sep 2007 18:10:48 -0000 1.100
--- src/include/storage/proc.h 23 Oct 2007 21:10:46 -0000
*************** struct XidCache
*** 38,43 ****
--- 38,47 ----
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS];
};
+ /* Flags for PGPROC->vacuumFlags */
+ #define PROC_IS_AUTOVACUUM (1 << 0) /* is it an autovac worker? */
+ #define PROC_IN_VACUUM (1 << 1) /* currently running lazy vacuum */
+
/*
* Each backend has a PGPROC struct in shared memory. There is also a list of
* currently-unused PGPROC structs that will be reallocated to new backends.
*************** struct PGPROC
*** 82,93 ****
bool inCommit; /* true if within commit critical section */
- bool inVacuum; /* true if current xact is a LAZY VACUUM */
- bool isAutovacuum; /* true if it's autovacuum */
-
/* Info about LWLock the process is currently waiting for, if any. */
bool lwWaiting; /* true if waiting for an LW lock */
bool lwExclusive; /* true if waiting for exclusive access */
struct PGPROC *lwWaitLink; /* next waiter for same LW lock */
/* Info about lock the process is currently waiting for, if any. */
--- 86,96 ----
bool inCommit; /* true if within commit critical section */
/* Info about LWLock the process is currently waiting for, if any. */
bool lwWaiting; /* true if waiting for an LW lock */
bool lwExclusive; /* true if waiting for exclusive access */
+
+ char vacuumFlags; /* vacuum-related flags, see above */
struct PGPROC *lwWaitLink; /* next waiter for same LW lock */
/* Info about lock the process is currently waiting for, if any. */
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faq