diff options
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r-- | src/backend/storage/ipc/procarray.c | 52 | ||||
-rw-r--r-- | src/backend/storage/ipc/procsignal.c | 16 | ||||
-rw-r--r-- | src/backend/storage/ipc/standby.c | 67 |
3 files changed, 58 insertions, 77 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 01a7c2123f1..6075de55c53 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.55 2010/01/10 15:44:28 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.56 2010/01/16 10:05:50 sriggs Exp $ * *------------------------------------------------------------------------- */ @@ -324,6 +324,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) /* must be cleared with xid/xmin: */ proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK; proc->inCommit = false; /* be sure this is cleared in abort */ + proc->recoveryConflictPending = false; /* Clear the subtransaction-XID cache too while holding the lock */ proc->subxids.nxids = 0; @@ -350,6 +351,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) /* must be cleared with xid/xmin: */ proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK; proc->inCommit = false; /* be sure this is cleared in abort */ + proc->recoveryConflictPending = false; Assert(proc->subxids.nxids == 0); Assert(proc->subxids.overflowed == false); @@ -377,7 +379,7 @@ ProcArrayClearTransaction(PGPROC *proc) proc->xid = InvalidTransactionId; proc->lxid = InvalidLocalTransactionId; proc->xmin = InvalidTransactionId; - proc->recoveryConflictMode = 0; + proc->recoveryConflictPending = false; /* redundant, but just in case */ proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK; @@ -1665,7 +1667,7 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid, if (proc->pid == 0) continue; - if (skipExistingConflicts && proc->recoveryConflictMode > 0) + if (skipExistingConflicts && proc->recoveryConflictPending) continue; if (!OidIsValid(dbOid) || @@ -1704,7 +1706,7 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid, * Returns pid of the process signaled, or 0 if not found. */ pid_t -CancelVirtualTransaction(VirtualTransactionId vxid, int cancel_mode) +CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode) { ProcArrayStruct *arrayP = procArray; int index; @@ -1722,28 +1724,22 @@ CancelVirtualTransaction(VirtualTransactionId vxid, int cancel_mode) if (procvxid.backendId == vxid.backendId && procvxid.localTransactionId == vxid.localTransactionId) { - /* - * Issue orders for the proc to read next time it receives SIGINT - */ - if (proc->recoveryConflictMode < cancel_mode) - proc->recoveryConflictMode = cancel_mode; - + proc->recoveryConflictPending = true; pid = proc->pid; + if (pid != 0) + { + /* + * Kill the pid if it's still here. If not, that's what we wanted + * so ignore any errors. + */ + (void) SendProcSignal(pid, sigmode, vxid.backendId); + } break; } } LWLockRelease(ProcArrayLock); - if (pid != 0) - { - /* - * Kill the pid if it's still here. If not, that's what we wanted - * so ignore any errors. - */ - kill(pid, SIGINT); - } - return pid; } @@ -1834,6 +1830,7 @@ CancelDBBackends(Oid databaseid) { ProcArrayStruct *arrayP = procArray; int index; + pid_t pid = 0; /* tell all backends to die */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); @@ -1844,8 +1841,21 @@ CancelDBBackends(Oid databaseid) if (proc->databaseId == databaseid) { - proc->recoveryConflictMode = CONFLICT_MODE_FATAL; - kill(proc->pid, SIGINT); + VirtualTransactionId procvxid; + + GET_VXID_FROM_PGPROC(procvxid, *proc); + + proc->recoveryConflictPending = true; + pid = proc->pid; + if (pid != 0) + { + /* + * Kill the pid if it's still here. If not, that's what we wanted + * so ignore any errors. + */ + (void) SendProcSignal(pid, PROCSIG_RECOVERY_CONFLICT_DATABASE, + procvxid.backendId); + } } } diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 753306ca295..453d94aea5b 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/procsignal.c,v 1.2 2010/01/02 16:57:51 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/procsignal.c,v 1.3 2010/01/16 10:05:50 sriggs Exp $ * *------------------------------------------------------------------------- */ @@ -24,6 +24,8 @@ #include "storage/procsignal.h" #include "storage/shmem.h" #include "storage/sinval.h" +#include "storage/standby.h" +#include "tcop/tcopprot.h" /* @@ -258,5 +260,17 @@ procsignal_sigusr1_handler(SIGNAL_ARGS) if (CheckProcSignal(PROCSIG_NOTIFY_INTERRUPT)) HandleNotifyInterrupt(); + if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_DATABASE)) + RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_DATABASE); + + if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_TABLESPACE)) + RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_TABLESPACE); + + if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_LOCK)) + RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_LOCK); + + if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT)) + RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT); + errno = save_errno; } diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index bc9302c4bca..5eca3c89dba 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -3,19 +3,15 @@ * standby.c * Misc functions used in Hot Standby mode. * - * InitRecoveryTransactionEnvironment() - * ShutdownRecoveryTransactionEnvironment() - * - * ResolveRecoveryConflictWithVirtualXIDs() - * * All functions for handling RM_STANDBY_ID, which relate to * AccessExclusiveLocks and starting snapshots for Hot Standby mode. + * Plus conflict recovery processing. * * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.4 2010/01/14 11:08:02 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.5 2010/01/16 10:05:50 sriggs Exp $ * *------------------------------------------------------------------------- */ @@ -38,7 +34,7 @@ int vacuum_defer_cleanup_age; static List *RecoveryLockList; static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, - char *reason, int cancel_mode); + ProcSignalReason reason); static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid); static void LogCurrentRunningXacts(RunningTransactions CurrRunningXacts); static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks); @@ -162,17 +158,13 @@ WaitExceedsMaxStandbyDelay(void) * recovery processing. Judgement has already been passed on it within * a specific rmgr. Here we just issue the orders to the procs. The procs * then throw the required error as instructed. - * - * We may ask for a specific cancel_mode, typically ERROR or FATAL. */ static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, - char *reason, int cancel_mode) + ProcSignalReason reason) { char waitactivitymsg[100]; - Assert(cancel_mode > 0); - while (VirtualTransactionIdIsValid(*waitlist)) { long wait_s; @@ -206,12 +198,6 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, len = 100; memcpy(waitactivitymsg, oldactivitymsg, len); - ereport(trace_recovery(DEBUG5), - (errmsg("virtual transaction %u/%u is blocking %s", - waitlist->backendId, - waitlist->localTransactionId, - reason))); - pgstat_report_waiting(true); logged = true; @@ -226,40 +212,14 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist, * Now find out who to throw out of the balloon. */ Assert(VirtualTransactionIdIsValid(*waitlist)); - pid = CancelVirtualTransaction(*waitlist, cancel_mode); + pid = CancelVirtualTransaction(*waitlist, reason); + /* + * Wait awhile for it to die so that we avoid flooding an + * unresponsive backend when system is heavily loaded. + */ if (pid != 0) - { - /* - * Startup process debug messages - */ - switch (cancel_mode) - { - case CONFLICT_MODE_FATAL: - elog(trace_recovery(DEBUG1), - "recovery disconnects session with pid %ld because of conflict with %s", - (long) pid, - reason); - break; - case CONFLICT_MODE_ERROR: - elog(trace_recovery(DEBUG1), - "recovery cancels virtual transaction %u/%u pid %ld because of conflict with %s", - waitlist->backendId, - waitlist->localTransactionId, - (long) pid, - reason); - break; - default: - /* No conflict pending, so fall through */ - break; - } - - /* - * Wait awhile for it to die so that we avoid flooding an - * unresponsive backend when system is heavily loaded. - */ pg_usleep(5000); - } } } @@ -285,8 +245,7 @@ ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid) true); ResolveRecoveryConflictWithVirtualXIDs(backends, - "snapshot conflict", - CONFLICT_MODE_ERROR); + PROCSIG_RECOVERY_CONFLICT_SNAPSHOT); } void @@ -317,8 +276,7 @@ ResolveRecoveryConflictWithTablespace(Oid tsid) InvalidOid, false); ResolveRecoveryConflictWithVirtualXIDs(temp_file_users, - "drop tablespace", - CONFLICT_MODE_ERROR); + PROCSIG_RECOVERY_CONFLICT_TABLESPACE); } void @@ -379,8 +337,7 @@ ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid) } ResolveRecoveryConflictWithVirtualXIDs(backends, - "exclusive lock", - CONFLICT_MODE_ERROR); + PROCSIG_RECOVERY_CONFLICT_LOCK); if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true, false) != LOCKACQUIRE_NOT_AVAIL) |