summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2007-01-16 13:28:57 +0000
committerAlvaro Herrera2007-01-16 13:28:57 +0000
commit2da2a01afb2f37ce13b63412d49db9ee99ab7674 (patch)
tree16ba1371993afc4faf42c9f496df0cb8aadd7439
parent24667ddd18b679321c08bd8bbfbe30bd4d0e252c (diff)
Arrange for autovacuum to be killed when another operation wants to be alone
accessing it, like DROP DATABASE. This allows the regression tests to pass with autovacuum enabled, which open the gates for finally enabling autovacuum by default.
-rw-r--r--src/backend/access/transam/twophase.c1
-rw-r--r--src/backend/commands/dbcommands.c10
-rw-r--r--src/backend/postmaster/autovacuum.c13
-rw-r--r--src/backend/postmaster/postmaster.c4
-rw-r--r--src/backend/storage/ipc/procarray.c29
-rw-r--r--src/backend/storage/lmgr/proc.c3
-rw-r--r--src/include/postmaster/autovacuum.h1
-rw-r--r--src/include/storage/proc.h1
-rw-r--r--src/include/storage/procarray.h2
9 files changed, 50 insertions, 14 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index f85c2c6842..636216f40a 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -280,6 +280,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
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;
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index a19695bab1..eb025ee6de 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -250,11 +250,11 @@ createdb(const CreatedbStmt *stmt)
* (exception is to allow CREATE DB while connected to template1).
* Otherwise we might copy inconsistent data.
*/
- if (DatabaseHasActiveBackends(src_dboid, true))
+ if (DatabaseCancelAutovacuumActivity(src_dboid, true))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("source database \"%s\" is being accessed by other users",
- dbtemplate)));
+ errmsg("source database \"%s\" is being accessed by other users",
+ dbtemplate)));
/* If encoding is defaulted, use source's encoding */
if (encoding < 0)
@@ -602,7 +602,7 @@ dropdb(const char *dbname, bool missing_ok)
* 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))
+ if (DatabaseCancelAutovacuumActivity(db_id, false))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("database \"%s\" is being accessed by other users",
@@ -706,7 +706,7 @@ RenameDatabase(const char *oldname, const char *newname)
* 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))
+ if (DatabaseCancelAutovacuumActivity(db_id, false))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("database \"%s\" is being accessed by other users",
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 68455e066c..42cfcfb6ec 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -216,6 +216,15 @@ autovac_forkexec(void)
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 */
/*
@@ -307,8 +316,8 @@ AutoVacMain(int argc, char *argv[])
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
+ * We can now go away. Note that because we called InitProcess, a
+ * callback was registered to do ProcKill, which will clean up
* necessary state.
*/
proc_exit(0);
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f5675231b6..36339ad999 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3298,6 +3298,10 @@ SubPostmasterMain(int argc, char *argv[])
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
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 79a41029cf..2d1493bb09 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -29,6 +29,8 @@
*/
#include "postgres.h"
+#include <signal.h>
+
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
@@ -678,7 +680,9 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
}
/*
- * DatabaseHasActiveBackends -- are there any backends running in the given DB
+ * 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.
@@ -691,11 +695,16 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
* backend startup.
*/
bool
-DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
+DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself)
{
- bool result = false;
ProcArrayStruct *arrayP = procArray;
int index;
+ int num;
+
+restart:
+ num = 0;
+
+ CHECK_FOR_INTERRUPTS();
LWLockAcquire(ProcArrayLock, LW_SHARED);
@@ -708,14 +717,22 @@ DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
if (ignoreMyself && proc == MyProc)
continue;
- result = true;
- break;
+ 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 result;
+ return (num != 0);
}
/*
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 2cb629aa4a..8cb1e0340c 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -38,6 +38,7 @@
#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"
@@ -258,6 +259,7 @@ InitProcess(void)
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inVacuum = false;
+ MyProc->isAutovacuum = IsAutoVacuumProcess();
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
@@ -390,6 +392,7 @@ InitDummyProcess(void)
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inVacuum = false;
+ MyProc->isAutovacuum = false;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index e83684441c..4c7671faa8 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -36,6 +36,7 @@ extern void autovac_stopped(void);
#ifdef EXEC_BACKEND
extern void AutoVacMain(int argc, char *argv[]);
+extern void AutovacuumIAm(void);
#endif
#endif /* AUTOVACUUM_H */
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index fed061bb29..0012c24133 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -75,6 +75,7 @@ struct PGPROC
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 */
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 7fe9988e53..583235d746 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -29,7 +29,7 @@ extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum);
extern PGPROC *BackendPidGetProc(int pid);
extern int BackendXidGetPid(TransactionId xid);
extern bool IsBackendPid(int pid);
-extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself);
+extern bool DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself);
extern int CountActiveBackends(void);
extern int CountDBBackends(Oid databaseid);