static Object[] look(AbstractPool factory, LockTable set,
LockControl control, ActiveLock startingLock,
byte deadlockWake) {
// step one, get a list of all waiters
Dictionary waiters = Deadlock.getWaiters(set);
// This stack will track the potential deadlock chain
// The Stack consists of
// start (Vector element 0)
// - Compatibility space of waiter A
// - Stack of compatibility spaces with granted lock for waiter A
Stack chain = new Stack();
chain.push(startingLock.getCompatabilitySpace());
chain.push(control.getGrants());
outer: for (;;) {
if (chain.isEmpty()) {
// all done
break outer;
}
List grants = (List) chain.peek();
if (grants.isEmpty()) {
// pop this list of granted locks and back to the previous one
rollback(chain);
continue outer;
}
int endStack = grants.size() - 1;
Object space = ((Lock) grants.get(endStack)).getCompatabilitySpace();
// this stack of granted locks can contain multiple entries
// for a single space. We don't want to do deadlock detection
// twice so check to see if we have seen this space already.
for (int gs = 0; gs < endStack; gs++) {
if (space.equals(((Lock) grants.get(gs)).getCompatabilitySpace())) {
chain.push(space); // set up as rollback() expects.
rollback(chain);
continue outer;
}
}
// find if this space is waiting on anyone
inner: for (;;) {
int index = chain.indexOf(space);
if (index != -1) {
// We could be seeing a situation here like
// Granted T1{S}, T2{S}
// Waiting T1{X} - deadlock checking on this
//
// In this case it's not a deadlock, although it
// depends on the locking policy of the Lockable. E.g.
// Granted T1(latch)
// Waiting T1(latch)
// is a deadlock.
//
if ((index == (chain.size() - 1)) ||
((index == (chain.size() - 2))
&& (index == (chain.indexOf(grants) - 1)))) {
// potential self deadlock, but probably not!
ActiveLock lock = (ActiveLock) waiters.get(space);
if (lock.canSkip) {
// not a deadlock ...
chain.push(space); // set up as rollback() expects.
rollback(chain);
continue outer;
}
}
return Deadlock.handle(factory, chain, index, waiters, deadlockWake);
}
chain.push(space);
Lock waitingLock = (Lock) waiters.get(space);
if (waitingLock == null) {
// end of the road, no deadlock in this path
// pop items until the previous Stack
rollback(chain);
continue outer;
}
// Is a LockControl or another ActiveLock
Object waitOn = waiters.get(waitingLock);
if (waitOn instanceof LockControl) {
LockControl waitOnControl = (LockControl) waitOn;
// This lock control may have waiters but no