static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid) { VirtualTransactionId *backends; bool lock_acquired = false; int num_attempts = 0; LOCKTAG locktag; SET_LOCKTAG_RELATION(locktag, dbOid, relOid); /* * If blowing away everybody with conflicting locks doesn't work, after * the first two attempts then we just start blowing everybody away until * it does work. We do this because its likely that we either have too * many locks and we just can't get one at all, or that there are many * people crowding for the same table. Recovery must win; the end * justifies the means. */ while (!lock_acquired) { if (++num_attempts < 3) backends = GetLockConflicts(&locktag, AccessExclusiveLock); else backends = GetConflictingVirtualXIDs(InvalidTransactionId, InvalidOid); ResolveRecoveryConflictWithVirtualXIDs(backends, PROCSIG_RECOVERY_CONFLICT_LOCK); if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true, false) != LOCKACQUIRE_NOT_AVAIL) lock_acquired = true; } }
/* * WaitForLockersMultiple * Wait until no transaction holds locks that conflict with the given * locktags at the given lockmode. * * To do this, obtain the current list of lockers, and wait on their VXIDs * until they are finished. * * Note we don't try to acquire the locks on the given locktags, only the VXIDs * of its lock holders; if somebody grabs a conflicting lock on the objects * after we obtained our initial list of lockers, we will not wait for them. */ void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode) { List *holders = NIL; ListCell *lc; /* Done if no locks to wait for */ if (list_length(locktags) == 0) return; /* Collect the transactions we need to wait on */ foreach(lc, locktags) { LOCKTAG *locktag = lfirst(lc); holders = lappend(holders, GetLockConflicts(locktag, lockmode)); }