/** * Test if a connection can be obtained * * @param subject Optional subject * @param cri Optional CRI * @return True if possible; otherwise false */ protected boolean internalTestConnection(ConnectionRequestInfo cri, Subject subject) { boolean result = false; ConnectionListener cl = null; try { boolean separateNoTx = false; if (noTxSeparatePools) { separateNoTx = clf.isTransactional(); } Object key = getKey(subject, cri, separateNoTx); ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri); if (mcp.getStatistics().getAvailableCount() > 0) { cl = mcp.getConnection(subject, cri); result = true; } } catch (Throwable ignored) { // Ignore } finally { if (cl != null) { try { returnConnection(cl, false); } catch (ResourceException ire) { // Ignore } } } return result; }
/** * Gets simple connection listener that wraps connection. * * @param subject Subject instance * @param cri Connection request info * @param mcp The managed connection pool * @return connection listener * @throws ResourceException ResourceException */ private ConnectionListener getSimpleConnection( final Subject subject, final ConnectionRequestInfo cri, final ManagedConnectionPool mcp) throws ResourceException { ConnectionListener cl = null; try { // Get connection from the managed connection pool cl = mcp.getConnection(subject, cri); if (trace) log.tracef("Got connection from pool: %s", cl); return cl; } catch (ResourceException re) { if (re instanceof RetryableException) { if (log.isDebugEnabled()) log.debug("Got a RetryableException - trying to reinitialize the pool"); // Make sure that the managed connection pool is running if (!mcp.isRunning()) mcp.reenable(); // Getting connection from pool cl = mcp.getConnection(subject, cri); if (trace) log.tracef("Got connection from pool (retried): %s", cl); return cl; } else { throw re; } } }
/** {@inheritDoc} */ public ConnectionListener findConnectionListener(ManagedConnection mc, Object connection) { for (ManagedConnectionPool mcp : mcpPools.values()) { ConnectionListener cl = mcp.findConnectionListener(mc, connection); if (cl != null) return cl; } return null; }
/** {@inheritDoc} */ public void returnConnection(ConnectionListener cl, boolean kill) throws ResourceException { cl.setTrackByTx(false); // Get connection listener pool ManagedConnectionPool mcp = cl.getManagedConnectionPool(); // Return connection to the pool mcp.returnConnection(cl, kill); if (trace) log.tracef("Returning connection to pool %s", cl); }
/** {@inheritDoc} */ public void shutdown() { log.debug(poolName + ": shutdown"); Iterator<ManagedConnectionPool> it = mcpPools.values().iterator(); while (it.hasNext()) { ManagedConnectionPool mcp = it.next(); mcp.shutdown(); } mcpPools.clear(); }
/** * Gets new connection listener if necessary instance with transaction. This method is package * protected beacause it is intended only for test case use. Please don't use it in your * production code. * * @param trackByTransaction transaction instance * @param mcp pool instance * @param subject subject instance * @param cri connection request info * @return connection listener instance * @throws ResourceException ResourceException */ ConnectionListener getTransactionNewConnection( Transaction trackByTransaction, ManagedConnectionPool mcp, Subject subject, ConnectionRequestInfo cri) throws ResourceException { // 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 (trace) log.tracef( "Got connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction); TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry(); Lock lock = getLock(); try { lock.lockInterruptibly(); } catch (InterruptedException ie) { Thread.interrupted(); throw new ResourceException(bundle.unableObtainLock(), ie); } try { // Check we weren't racing with another transaction ConnectionListener other = (ConnectionListener) tsr.getResource(mcp); if (other != null) { mcp.returnConnection(cl, false); if (trace) log.tracef( "Another thread already got a connection tracked by transaction=%s tx=%s", other, trackByTransaction); cl = other; } // This is the connection for this transaction cl.setTrackByTx(true); tsr.putResource(mcp, cl); if (trace) log.tracef( "Using connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction); return cl; } finally { lock.unlock(); } }
/** {@inheritDoc} */ public synchronized void emptyManagedConnectionPool(ManagedConnectionPool pool) { log.debug(poolName + ": emptyManagedConnectionPool(" + pool + ")"); if (pool != null) { // We only consider removal if there are more than 1 managed connection pool if (mcpPools.size() > 1) { Iterator<ManagedConnectionPool> it = mcpPools.values().iterator(); while (it.hasNext()) { ManagedConnectionPool other = it.next(); if (other == pool && pool.isEmpty()) { pool.shutdown(); it.remove(); break; } } } } }
/** {@inheritDoc} */ public synchronized void flush(FlushMode mode) { log.debug(poolName + ": flush(" + mode + ")"); Set<ManagedConnectionPool> clearMcpPools = new HashSet<ManagedConnectionPool>(); Iterator<ManagedConnectionPool> it = mcpPools.values().iterator(); while (it.hasNext()) { ManagedConnectionPool mcp = it.next(); mcp.flush(mode); if (mcp.isEmpty()) clearMcpPools.add(mcp); } if (clearMcpPools.size() > 0) { for (ManagedConnectionPool mcp : clearMcpPools) { mcp.shutdown(); mcpPools.values().remove(mcp); } } }