use of org.datanucleus.store.rdbms.datasource.dbcp2.pool2.PooledObject in project datanucleus-rdbms by datanucleus.
the class GenericKeyedObjectPool method evict.
/**
* {@inheritDoc}
* <p>
* Successive activations of this method examine objects in keyed sub-pools
* in sequence, cycling through the keys and examining objects in
* oldest-to-youngest order within the keyed sub-pools.
*/
@Override
public void evict() throws Exception {
assertOpen();
if (getNumIdle() == 0) {
return;
}
PooledObject<T> underTest = null;
final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
synchronized (evictionLock) {
final EvictionConfig evictionConfig = new EvictionConfig(getMinEvictableIdleTimeMillis(), getSoftMinEvictableIdleTimeMillis(), getMinIdlePerKey());
final boolean testWhileIdle = getTestWhileIdle();
for (int i = 0, m = getNumTests(); i < m; i++) {
if (evictionIterator == null || !evictionIterator.hasNext()) {
if (evictionKeyIterator == null || !evictionKeyIterator.hasNext()) {
final List<K> keyCopy = new ArrayList<>();
final Lock readLock = keyLock.readLock();
readLock.lock();
try {
keyCopy.addAll(poolKeyList);
} finally {
readLock.unlock();
}
evictionKeyIterator = keyCopy.iterator();
}
while (evictionKeyIterator.hasNext()) {
evictionKey = evictionKeyIterator.next();
final ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
if (objectDeque == null) {
continue;
}
final Deque<PooledObject<T>> idleObjects = objectDeque.getIdleObjects();
evictionIterator = new EvictionIterator(idleObjects);
if (evictionIterator.hasNext()) {
break;
}
evictionIterator = null;
}
}
if (evictionIterator == null) {
// Pools exhausted
return;
}
final Deque<PooledObject<T>> idleObjects;
try {
underTest = evictionIterator.next();
idleObjects = evictionIterator.getIdleObjects();
} catch (final NoSuchElementException nsee) {
// Object was borrowed in another thread
// Don't count this as an eviction test so reduce i;
i--;
evictionIterator = null;
continue;
}
if (!underTest.startEvictionTest()) {
// Object was borrowed in another thread
// Don't count this as an eviction test so reduce i;
i--;
continue;
}
// User provided eviction policy could throw all sorts of
// crazy exceptions. Protect against such an exception
// killing the eviction thread.
boolean evict;
try {
evict = evictionPolicy.evict(evictionConfig, underTest, poolMap.get(evictionKey).getIdleObjects().size());
} catch (final Throwable t) {
// Slightly convoluted as SwallowedExceptionListener
// uses Exception rather than Throwable
PoolUtils.checkRethrow(t);
swallowException(new Exception(t));
// Don't evict on error conditions
evict = false;
}
if (evict) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
} else {
if (testWhileIdle) {
boolean active = false;
try {
factory.activateObject(evictionKey, underTest);
active = true;
} catch (final Exception e) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
}
if (active) {
if (!factory.validateObject(evictionKey, underTest)) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
} else {
try {
factory.passivateObject(evictionKey, underTest);
} catch (final Exception e) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
}
}
}
}
if (!underTest.endEvictionTest(idleObjects)) {
// TODO - May need to add code here once additional
// states are used
}
}
}
}
}
use of org.datanucleus.store.rdbms.datasource.dbcp2.pool2.PooledObject in project datanucleus-rdbms by datanucleus.
the class PoolableConnectionFactory method makeObject.
@Override
public PooledObject<PoolableConnection> makeObject() throws Exception {
Connection conn = connectionFactory.createConnection();
if (conn == null) {
throw new IllegalStateException("Connection factory returned null from createConnection");
}
try {
initializeConnection(conn);
} catch (final SQLException sqle) {
// Make sure the connection is closed
try {
conn.close();
} catch (final SQLException ignore) {
// ignore
}
// Rethrow original exception so it is visible to caller
throw sqle;
}
final long connIndex = connectionIndex.getAndIncrement();
if (poolStatements) {
conn = new PoolingConnection(conn);
final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
config.setMaxTotalPerKey(-1);
config.setBlockWhenExhausted(false);
config.setMaxWaitMillis(0);
config.setMaxIdlePerKey(1);
config.setMaxTotal(maxOpenPreparedStatements);
if (dataSourceJmxObjectName != null) {
final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString());
base.append(Constants.JMX_CONNECTION_BASE_EXT);
base.append(Long.toString(connIndex));
config.setJmxNameBase(base.toString());
config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX);
} else {
config.setJmxEnabled(false);
}
final PoolingConnection poolingConn = (PoolingConnection) conn;
final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config);
poolingConn.setStatementPool(stmtPool);
poolingConn.setCacheState(cacheState);
}
// Register this connection with JMX
ObjectName connJmxName;
if (dataSourceJmxObjectName == null) {
connJmxName = null;
} else {
connJmxName = new ObjectName(dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex);
}
final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation);
pc.setCacheState(cacheState);
return new DefaultPooledObject<>(pc);
}
use of org.datanucleus.store.rdbms.datasource.dbcp2.pool2.PooledObject in project new-cloud by xie-summer.
the class JedisPoolTest method returnResourceDestroysResourceOnException.
@Test
public void returnResourceDestroysResourceOnException() {
class CrashingJedis extends Jedis {
@Override
public void resetState() {
throw new RuntimeException();
}
}
final AtomicInteger destroyed = new AtomicInteger(0);
class CrashingJedisPooledObjectFactory implements PooledObjectFactory<Jedis> {
@Override
public PooledObject<Jedis> makeObject() throws Exception {
return new DefaultPooledObject<Jedis>(new CrashingJedis());
}
@Override
public void destroyObject(PooledObject<Jedis> p) throws Exception {
destroyed.incrementAndGet();
}
@Override
public boolean validateObject(PooledObject<Jedis> p) {
return true;
}
@Override
public void activateObject(PooledObject<Jedis> p) throws Exception {
}
@Override
public void passivateObject(PooledObject<Jedis> p) throws Exception {
}
}
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, "foobared");
pool.initPool(config, new CrashingJedisPooledObjectFactory());
Jedis crashingJedis = pool.getResource();
try {
crashingJedis.close();
} catch (Exception ignored) {
}
assertEquals(destroyed.get(), 1);
}
use of org.datanucleus.store.rdbms.datasource.dbcp2.pool2.PooledObject in project datanucleus-rdbms by datanucleus.
the class GenericObjectPool method returnObject.
/**
* {@inheritDoc}
* <p>
* If {@link #getMaxIdle() maxIdle} is set to a positive value and the
* number of idle instances has reached this value, the returning instance
* is destroyed.
* <p>
* If {@link #getTestOnReturn() testOnReturn} == true, the returning
* instance is validated before being returned to the idle instance pool. In
* this case, if validation fails, the instance is destroyed.
* <p>
* Exceptions encountered destroying objects for any reason are swallowed
* but notified via a {@link SwallowedExceptionListener}.
*/
@Override
public void returnObject(T obj) {
PooledObject<T> p = allObjects.get(new IdentityWrapper<T>(obj));
if (p == null) {
if (!isAbandonedConfig()) {
throw new IllegalStateException("Returned object not currently part of this pool");
}
// Object was abandoned and removed
return;
}
synchronized (p) {
final PooledObjectState state = p.getState();
if (state != PooledObjectState.ALLOCATED) {
throw new IllegalStateException("Object has already been returned to this pool or is invalid");
}
// Keep from being marked abandoned
p.markReturning();
}
long activeTime = p.getActiveTimeMillis();
if (getTestOnReturn()) {
if (!factory.validateObject(p)) {
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
} catch (Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
return;
}
}
try {
factory.passivateObject(p);
} catch (Exception e1) {
swallowException(e1);
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
} catch (Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
return;
}
if (!p.deallocate()) {
throw new IllegalStateException("Object has already been returned to this pool or is invalid");
}
int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
} else {
if (getLifo()) {
idleObjects.addFirst(p);
} else {
idleObjects.addLast(p);
}
if (isClosed()) {
// Pool closed while object was being added to idle objects.
// Make sure the returned object is destroyed rather than left
// in the idle object pool (which would effectively be a leak)
clear();
}
}
updateStatsReturn(activeTime);
}
use of org.datanucleus.store.rdbms.datasource.dbcp2.pool2.PooledObject in project datanucleus-rdbms by datanucleus.
the class PooledConnectionImpl method passivateObject.
/**
* My {@link KeyedPooledObjectFactory} method for passivating {@link PreparedStatement}s. Currently invokes
* {@link PreparedStatement#clearParameters}.
*
* @param key
* ignored
* @param pooledObject
* a wrapped {@link PreparedStatement}
*/
@Override
public void passivateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject) throws Exception {
@SuppressWarnings("resource") final DelegatingPreparedStatement dps = pooledObject.getObject();
dps.clearParameters();
dps.passivate();
}
Aggregations