Alvaro Herrera wrote: > Tom Lane wrote: > > Alvaro Herrera <[EMAIL PROTECTED]> writes: > > > Here it is. > > > > I'd drop the InitProcess API change, which touches many more places than > > you really need, and just have InitProcess check IsAutoVacuumProcess(), > > which should be valid by the time control gets to it. This is more like > > the way that InitPostgres handles it, anyway. > > Hmm, the problem is SubPostmasterMain, which is in the EXEC_BACKEND > path. It hasn't reached the autovacuum.c code yet, so it hasn't had the > chance to set the am_autovacuum static variable (in autovacuum.c). I > guess the answer here is to allow that variable to be set from the > outside.
New version of the patch attached. I'll probably apply this tomorrow morning unless there are objections. An important difference from the previous patch is that DatabaseHasActiveBackends (now renamed to DatabaseCancelAutovacuumActivity) cycles through the whole ProcArray instead of stopping at the first occurence of a backend in that database. This is to be able to fulfill its mission of cancelling *any* autovacuum activity that may be taking place on the database (not just the one that happens to be below the first process in the ProcArray). I also tried the EXEC_BACKEND case (albeit less extensively) and it seems to work -- it cancels running autovacuums at least. -- Alvaro Herrera http://www.CommandPrompt.com/ The PostgreSQL Company - Command Prompt, Inc.
Index: src/backend/access/transam/twophase.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/access/transam/twophase.c,v retrieving revision 1.26 diff -c -p -r1.26 twophase.c *** src/backend/access/transam/twophase.c 5 Jan 2007 22:19:23 -0000 1.26 --- src/backend/access/transam/twophase.c 15 Jan 2007 19:11:15 -0000 *************** MarkAsPreparing(TransactionId xid, const *** 280,285 **** --- 280,286 ---- gxact->proc.databaseId = databaseid; gxact->proc.roleId = owner; gxact->proc.inVacuum = false; + gxact->proc.isAutovacuum = false; gxact->proc.lwWaiting = false; gxact->proc.lwExclusive = false; gxact->proc.lwWaitLink = NULL; Index: src/backend/commands/dbcommands.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/dbcommands.c,v retrieving revision 1.188 diff -c -p -r1.188 dbcommands.c *** src/backend/commands/dbcommands.c 5 Jan 2007 22:19:25 -0000 1.188 --- src/backend/commands/dbcommands.c 15 Jan 2007 22:00:56 -0000 *************** createdb(const CreatedbStmt *stmt) *** 250,260 **** * (exception is to allow CREATE DB while connected to template1). * Otherwise we might copy inconsistent data. */ ! if (DatabaseHasActiveBackends(src_dboid, true)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), ! errmsg("source database \"%s\" is being accessed by other users", ! dbtemplate))); /* If encoding is defaulted, use source's encoding */ if (encoding < 0) --- 250,260 ---- * (exception is to allow CREATE DB while connected to template1). * Otherwise we might copy inconsistent data. */ ! if (DatabaseCancelAutovacuumActivity(src_dboid, true)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), ! errmsg("source database \"%s\" is being accessed by other users", ! dbtemplate))); /* If encoding is defaulted, use source's encoding */ if (encoding < 0) *************** dropdb(const char *dbname, bool missing_ *** 602,608 **** * Check for active backends in the target database. (Because we hold the * database lock, no new ones can start after this.) */ ! if (DatabaseHasActiveBackends(db_id, false)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("database \"%s\" is being accessed by other users", --- 602,608 ---- * Check for active backends in the target database. (Because we hold the * database lock, no new ones can start after this.) */ ! if (DatabaseCancelAutovacuumActivity(db_id, false)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("database \"%s\" is being accessed by other users", *************** RenameDatabase(const char *oldname, cons *** 706,712 **** * Make sure the database does not have active sessions. This is the same * concern as above, but applied to other sessions. */ ! if (DatabaseHasActiveBackends(db_id, false)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("database \"%s\" is being accessed by other users", --- 706,712 ---- * Make sure the database does not have active sessions. This is the same * concern as above, but applied to other sessions. */ ! if (DatabaseCancelAutovacuumActivity(db_id, false)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("database \"%s\" is being accessed by other users", Index: src/backend/postmaster/autovacuum.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/autovacuum.c,v retrieving revision 1.30 diff -c -p -r1.30 autovacuum.c *** src/backend/postmaster/autovacuum.c 5 Jan 2007 22:19:36 -0000 1.30 --- src/backend/postmaster/autovacuum.c 15 Jan 2007 21:48:08 -0000 *************** autovac_forkexec(void) *** 216,221 **** --- 216,230 ---- return postmaster_forkexec(ac, av); } + + /* + * We need this set from the outside, before InitProcess is called + */ + void + AutovacuumIAm(void) + { + am_autovacuum = true; + } #endif /* EXEC_BACKEND */ /* *************** AutoVacMain(int argc, char *argv[]) *** 307,313 **** EmitErrorReport(); /* ! * We can now go away. Note that because we'll call InitProcess, a * callback will be registered to do ProcKill, which will clean up * necessary state. */ --- 316,322 ---- EmitErrorReport(); /* ! * We can now go away. Note that because we called InitProcess, a * callback will be registered to do ProcKill, which will clean up * necessary state. */ Index: src/backend/postmaster/postmaster.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/postmaster.c,v retrieving revision 1.507 diff -c -p -r1.507 postmaster.c *** src/backend/postmaster/postmaster.c 5 Jan 2007 22:19:36 -0000 1.507 --- src/backend/postmaster/postmaster.c 15 Jan 2007 21:48:20 -0000 *************** SubPostmasterMain(int argc, char *argv[] *** 3298,3303 **** --- 3298,3307 ---- strcmp(argv[1], "--forkboot") == 0) PGSharedMemoryReAttach(); + /* autovacuum needs this set before calling InitProcess */ + if (strcmp(argv[1], "--forkautovac") == 0) + AutovacuumIAm(); + /* * Start our win32 signal implementation. This has to be done after we * read the backend variables, because we need to pick up the signal pipe Index: src/backend/storage/ipc/procarray.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/ipc/procarray.c,v retrieving revision 1.20 diff -c -p -r1.20 procarray.c *** src/backend/storage/ipc/procarray.c 5 Jan 2007 22:19:38 -0000 1.20 --- src/backend/storage/ipc/procarray.c 15 Jan 2007 22:08:48 -0000 *************** *** 29,34 **** --- 29,36 ---- */ #include "postgres.h" + #include <signal.h> + #include "access/subtrans.h" #include "access/transam.h" #include "access/xact.h" *************** GetSnapshotData(Snapshot snapshot, bool *** 678,684 **** } /* ! * DatabaseHasActiveBackends -- are there any backends running in the given DB * * If 'ignoreMyself' is TRUE, ignore this particular backend while checking * for backends in the target database. --- 680,688 ---- } /* ! * DatabaseCancelAutovacuumActivity -- are there any backends running in the ! * given DB, apart from autovacuum? If an autovacuum process is running on the ! * database, kill it and restart the counting. * * If 'ignoreMyself' is TRUE, ignore this particular backend while checking * for backends in the target database. *************** GetSnapshotData(Snapshot snapshot, bool *** 691,701 **** * backend startup. */ bool ! DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself) { - bool result = false; ProcArrayStruct *arrayP = procArray; int index; LWLockAcquire(ProcArrayLock, LW_SHARED); --- 695,710 ---- * backend startup. */ bool ! DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself) { ProcArrayStruct *arrayP = procArray; int index; + int num; + + restart: + num = 0; + + CHECK_FOR_INTERRUPTS(); LWLockAcquire(ProcArrayLock, LW_SHARED); *************** DatabaseHasActiveBackends(Oid databaseId *** 708,721 **** if (ignoreMyself && proc == MyProc) continue; ! result = true; ! break; } } LWLockRelease(ProcArrayLock); ! return result; } /* --- 717,738 ---- if (ignoreMyself && proc == MyProc) continue; ! num++; ! ! if (proc->isAutovacuum) ! { ! /* an autovacuum -- kill it and restart */ ! LWLockRelease(ProcArrayLock); ! kill(proc->pid, SIGINT); ! pg_usleep(100 * 1000); /* 100ms */ ! goto restart; ! } } } LWLockRelease(ProcArrayLock); ! return (num != 0); } /* Index: src/backend/storage/lmgr/proc.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/lmgr/proc.c,v retrieving revision 1.182 diff -c -p -r1.182 proc.c *** src/backend/storage/lmgr/proc.c 5 Jan 2007 22:19:38 -0000 1.182 --- src/backend/storage/lmgr/proc.c 15 Jan 2007 22:03:04 -0000 *************** *** 38,43 **** --- 38,44 ---- #include "access/transam.h" #include "access/xact.h" #include "miscadmin.h" + #include "postmaster/autovacuum.h" #include "storage/ipc.h" #include "storage/proc.h" #include "storage/procarray.h" *************** InitProcess(void) *** 258,263 **** --- 259,265 ---- MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->inVacuum = false; + MyProc->isAutovacuum = IsAutoVacuumProcess(); MyProc->lwWaiting = false; MyProc->lwExclusive = false; MyProc->lwWaitLink = NULL; *************** InitDummyProcess(void) *** 390,395 **** --- 392,398 ---- MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->inVacuum = false; + MyProc->isAutovacuum = false; MyProc->lwWaiting = false; MyProc->lwExclusive = false; MyProc->lwWaitLink = NULL; Index: src/include/postmaster/autovacuum.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/postmaster/autovacuum.h,v retrieving revision 1.6 diff -c -p -r1.6 autovacuum.h *** src/include/postmaster/autovacuum.h 5 Jan 2007 22:19:57 -0000 1.6 --- src/include/postmaster/autovacuum.h 15 Jan 2007 21:47:00 -0000 *************** extern void autovac_stopped(void); *** 36,41 **** --- 36,42 ---- #ifdef EXEC_BACKEND extern void AutoVacMain(int argc, char *argv[]); + extern void AutovacuumIAm(void); #endif #endif /* AUTOVACUUM_H */ Index: src/include/storage/proc.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/storage/proc.h,v retrieving revision 1.92 diff -c -p -r1.92 proc.h *** src/include/storage/proc.h 5 Jan 2007 22:19:58 -0000 1.92 --- src/include/storage/proc.h 15 Jan 2007 20:49:10 -0000 *************** struct PGPROC *** 75,80 **** --- 75,81 ---- Oid roleId; /* OID of role using this backend */ 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 */ Index: src/include/storage/procarray.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/storage/procarray.h,v retrieving revision 1.11 diff -c -p -r1.11 procarray.h *** src/include/storage/procarray.h 5 Jan 2007 22:19:58 -0000 1.11 --- src/include/storage/procarray.h 15 Jan 2007 22:00:08 -0000 *************** extern TransactionId GetOldestXmin(bool *** 29,35 **** extern PGPROC *BackendPidGetProc(int pid); extern int BackendXidGetPid(TransactionId xid); extern bool IsBackendPid(int pid); ! extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself); extern int CountActiveBackends(void); extern int CountDBBackends(Oid databaseid); --- 29,35 ---- extern PGPROC *BackendPidGetProc(int pid); extern int BackendXidGetPid(TransactionId xid); extern bool IsBackendPid(int pid); ! extern bool DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself); extern int CountActiveBackends(void); extern int CountDBBackends(Oid databaseid);
---------------------------(end of broadcast)--------------------------- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly