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)
{
try
{
ConnectionListener cl = mcp.getConnection(subject, cri);
if (traceEnabled)
dump("Got connection from pool " + cl);
return cl;
}
catch (RetryableResourceException rre)
{
if (log.isDebugEnabled())
log.debug("Got a RetryableResourceException - trying to reinitialize the pool");
// The IMCP is down - retry
subPool = getSubPool(key, subject, cri);
mcp = subPool.getSubPool();
// Make sure that IMCP is running
if (!mcp.isRunning())
mcp.initialize();
ConnectionListener cl = mcp.getConnection(subject, cri);
if (traceEnabled)
dump("Got connection from pool (retried) " + 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);
trackByTx.set(cl);
if (traceEnabled)
dump("Using connection from pool tracked by transaction " + cl + " tx=" + trackByTransaction);
return cl;
}
finally
{
trackByTx.unlock(trackByTransaction);
}
}