SubPoolContext subPool = getSubPool(key, subject, cri);
InternalManagedConnectionPool mcp = subPool.getSubPool();
// Are we doing track by connection?
TransactionLocal trackByTx = subPool.getTrackByTx();
// Simple case
if (trackByTransaction == null || trackByTx == null) {
ConnectionListener cl = mcp.getConnection(subject, cri);
if (traceEnabled)
dump("Got connection from pool " + cl);
return cl;
}
// Track by transaction
try {
trackByTx.lock(trackByTransaction);
} catch (Throwable t) {
JBossResourceException.rethrowAsResourceException("Unable to get connection from the pool for tx="
+ trackByTransaction, t);
}
try {
// Already got one
ConnectionListener cl = (ConnectionListener) trackByTx.get(trackByTransaction);
if (cl != null) {
if (traceEnabled)
dump("Previous connection tracked by transaction " + cl + " tx=" + trackByTransaction);
return cl;
}
} finally {
trackByTx.unlock(trackByTransaction);
}
// Need a new one for this transaction
// This must be done outside the tx local lock, otherwise
// the tx timeout won't work and get connection can do a lot of
// other work
// with many opportunities for deadlocks.
// Instead we do a double check after we got the transaction to see
// whether another thread beat us to the punch.
ConnectionListener cl = mcp.getConnection(subject, cri);
if (traceEnabled)
dump("Got connection from pool tracked by transaction " + cl + " tx=" + trackByTransaction);
// Relock and check/set status
try {
trackByTx.lock(trackByTransaction);
} catch (Throwable t) {
mcp.returnConnection(cl, false);
if (traceEnabled)
dump("Had to return connection tracked by transaction " + cl + " tx=" + trackByTransaction
+ " error=" + t.getMessage());
JBossResourceException.rethrowAsResourceException("Unable to get connection from the pool for tx="
+ trackByTransaction, t);
}
try {
// Check we weren't racing with another transaction
ConnectionListener other = (ConnectionListener) trackByTx.get(trackByTransaction);
if (other != null) {
mcp.returnConnection(cl, false);
if (traceEnabled)
dump("Another thread already got a connection tracked by transaction " + other + " tx="
+ trackByTransaction);
return other;
}
// This is the connection for this transaction
cl.setTrackByTx(true);
// FIXME Ӧ����trackByTx.set(trackByTransaction, cl)�ɣ�
trackByTx.set(cl);
if (traceEnabled)
dump("Using connection from pool tracked by transaction " + cl + " tx=" + trackByTransaction);
return cl;
} finally {
trackByTx.unlock(trackByTransaction);
}
}