You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2016/05/13 16:48:56 UTC
svn commit: r1743698 [2/3] - in /tomcat/trunk:
java/org/apache/tomcat/dbcp/pool2/ java/org/apache/tomcat/dbcp/pool2/impl/
webapps/docs/
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java?rev=1743698&r1=1743697&r2=1743698&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java Fri May 13 16:48:56 2016
@@ -80,7 +80,7 @@ public class GenericKeyedObjectPool<K,T>
* {@link GenericKeyedObjectPoolConfig}.
* @param factory the factory to be used to create entries
*/
- public GenericKeyedObjectPool(KeyedPooledObjectFactory<K,T> factory) {
+ public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K,T> factory) {
this(factory, new GenericKeyedObjectPoolConfig());
}
@@ -94,8 +94,8 @@ public class GenericKeyedObjectPool<K,T>
* the configuration object will not be reflected in the
* pool.
*/
- public GenericKeyedObjectPool(KeyedPooledObjectFactory<K,T> factory,
- GenericKeyedObjectPoolConfig config) {
+ public GenericKeyedObjectPool(final KeyedPooledObjectFactory<K,T> factory,
+ final GenericKeyedObjectPoolConfig config) {
super(config, ONAME_BASE, config.getJmxNamePrefix());
@@ -134,7 +134,7 @@ public class GenericKeyedObjectPool<K,T>
*
* @see #getMaxTotalPerKey
*/
- public void setMaxTotalPerKey(int maxTotalPerKey) {
+ public void setMaxTotalPerKey(final int maxTotalPerKey) {
this.maxTotalPerKey = maxTotalPerKey;
}
@@ -175,7 +175,7 @@ public class GenericKeyedObjectPool<K,T>
*
* @see #getMaxIdlePerKey
*/
- public void setMaxIdlePerKey(int maxIdlePerKey) {
+ public void setMaxIdlePerKey(final int maxIdlePerKey) {
this.maxIdlePerKey = maxIdlePerKey;
}
@@ -197,7 +197,7 @@ public class GenericKeyedObjectPool<K,T>
* @see #getMaxIdlePerKey()
* @see #setTimeBetweenEvictionRunsMillis
*/
- public void setMinIdlePerKey(int minIdlePerKey) {
+ public void setMinIdlePerKey(final int minIdlePerKey) {
this.minIdlePerKey = minIdlePerKey;
}
@@ -219,7 +219,7 @@ public class GenericKeyedObjectPool<K,T>
*/
@Override
public int getMinIdlePerKey() {
- int maxIdlePerKeySave = getMaxIdlePerKey();
+ final int maxIdlePerKeySave = getMaxIdlePerKey();
if (this.minIdlePerKey > maxIdlePerKeySave) {
return maxIdlePerKeySave;
}
@@ -233,7 +233,7 @@ public class GenericKeyedObjectPool<K,T>
*
* @see GenericKeyedObjectPoolConfig
*/
- public void setConfig(GenericKeyedObjectPoolConfig conf) {
+ public void setConfig(final GenericKeyedObjectPoolConfig conf) {
setLifo(conf.getLifo());
setMaxIdlePerKey(conf.getMaxIdlePerKey());
setMaxTotalPerKey(conf.getMaxTotalPerKey());
@@ -271,7 +271,7 @@ public class GenericKeyedObjectPool<K,T>
* {@inheritDoc}
*/
@Override
- public T borrowObject(K key) throws Exception {
+ public T borrowObject(final K key) throws Exception {
return borrowObject(key, getMaxWaitMillis());
}
@@ -331,30 +331,30 @@ public class GenericKeyedObjectPool<K,T>
* @throws Exception if a keyed object instance cannot be returned due to an
* error
*/
- public T borrowObject(K key, long borrowMaxWaitMillis) throws Exception {
+ public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception {
assertOpen();
PooledObject<T> p = null;
// Get local copy of current config so it is consistent for entire
// method execution
- boolean blockWhenExhausted = getBlockWhenExhausted();
+ final boolean blockWhenExhausted = getBlockWhenExhausted();
boolean create;
- long waitTime = System.currentTimeMillis();
- ObjectDeque<T> objectDeque = register(key);
+ final long waitTime = System.currentTimeMillis();
+ final ObjectDeque<T> objectDeque = register(key);
try {
while (p == null) {
create = false;
- if (blockWhenExhausted) {
- p = objectDeque.getIdleObjects().pollFirst();
- if (p == null) {
- p = create(key);
- if (p != null) {
- create = true;
- }
+ p = objectDeque.getIdleObjects().pollFirst();
+ if (p == null) {
+ p = create(key);
+ if (p != null) {
+ create = true;
}
+ }
+ if (blockWhenExhausted) {
if (p == null) {
if (borrowMaxWaitMillis < 0) {
p = objectDeque.getIdleObjects().takeFirst();
@@ -367,37 +367,27 @@ public class GenericKeyedObjectPool<K,T>
throw new NoSuchElementException(
"Timeout waiting for idle object");
}
- if (!p.allocate()) {
- p = null;
- }
} else {
- p = objectDeque.getIdleObjects().pollFirst();
- if (p == null) {
- p = create(key);
- if (p != null) {
- create = true;
- }
- }
if (p == null) {
throw new NoSuchElementException("Pool exhausted");
}
- if (!p.allocate()) {
- p = null;
- }
+ }
+ if (!p.allocate()) {
+ p = null;
}
if (p != null) {
try {
factory.activateObject(key, p);
- } catch (Exception e) {
+ } catch (final Exception e) {
try {
destroy(key, p, true);
- } catch (Exception e1) {
+ } catch (final Exception e1) {
// Ignore - activation failure is more important
}
p = null;
if (create) {
- NoSuchElementException nsee = new NoSuchElementException(
+ final NoSuchElementException nsee = new NoSuchElementException(
"Unable to activate object");
nsee.initCause(e);
throw nsee;
@@ -408,7 +398,7 @@ public class GenericKeyedObjectPool<K,T>
Throwable validationThrowable = null;
try {
validate = factory.validateObject(key, p);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
PoolUtils.checkRethrow(t);
validationThrowable = t;
}
@@ -416,12 +406,12 @@ public class GenericKeyedObjectPool<K,T>
try {
destroy(key, p, true);
destroyedByBorrowValidationCount.incrementAndGet();
- } catch (Exception e) {
+ } catch (final Exception e) {
// Ignore - validation failure is more important
}
p = null;
if (create) {
- NoSuchElementException nsee = new NoSuchElementException(
+ final NoSuchElementException nsee = new NoSuchElementException(
"Unable to validate object");
nsee.initCause(validationThrowable);
throw nsee;
@@ -464,11 +454,11 @@ public class GenericKeyedObjectPool<K,T>
* returned to the pool multiple times
*/
@Override
- public void returnObject(K key, T obj) {
+ public void returnObject(final K key, final T obj) {
- ObjectDeque<T> objectDeque = poolMap.get(key);
+ final ObjectDeque<T> objectDeque = poolMap.get(key);
- PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
+ final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
if (p == null) {
throw new IllegalStateException(
@@ -484,81 +474,80 @@ public class GenericKeyedObjectPool<K,T>
p.markReturning(); // Keep from being marked abandoned (once GKOP does this)
}
- long activeTime = p.getActiveTimeMillis();
+ final long activeTime = p.getActiveTimeMillis();
- if (getTestOnReturn()) {
- if (!factory.validateObject(key, p)) {
+ try {
+ if (getTestOnReturn()) {
+ if (!factory.validateObject(key, p)) {
+ try {
+ destroy(key, p, true);
+ } catch (final Exception e) {
+ swallowException(e);
+ }
+ if (objectDeque.idleObjects.hasTakeWaiters()) {
+ try {
+ addObject(key);
+ } catch (final Exception e) {
+ swallowException(e);
+ }
+ }
+ return;
+ }
+ }
+
+ try {
+ factory.passivateObject(key, p);
+ } catch (final Exception e1) {
+ swallowException(e1);
try {
destroy(key, p, true);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
if (objectDeque.idleObjects.hasTakeWaiters()) {
try {
addObject(key);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
}
- updateStatsReturn(activeTime);
return;
}
- }
- try {
- factory.passivateObject(key, p);
- } catch (Exception e1) {
- swallowException(e1);
- try {
- destroy(key, p, true);
- } catch (Exception e) {
- swallowException(e);
+ if (!p.deallocate()) {
+ throw new IllegalStateException(
+ "Object has already been returned to this pool");
}
- if (objectDeque.idleObjects.hasTakeWaiters()) {
+
+ final int maxIdle = getMaxIdlePerKey();
+ final LinkedBlockingDeque<PooledObject<T>> idleObjects =
+ objectDeque.getIdleObjects();
+
+ if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
try {
- addObject(key);
- } catch (Exception e) {
+ destroy(key, p, true);
+ } catch (final Exception e) {
swallowException(e);
}
- }
- updateStatsReturn(activeTime);
- return;
- }
-
- if (!p.deallocate()) {
- throw new IllegalStateException(
- "Object has already been returned to this pool");
- }
-
- int maxIdle = getMaxIdlePerKey();
- LinkedBlockingDeque<PooledObject<T>> idleObjects =
- objectDeque.getIdleObjects();
-
- if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {
- try {
- destroy(key, p, true);
- } catch (Exception e) {
- swallowException(e);
- }
- } else {
- if (getLifo()) {
- idleObjects.addFirst(p);
} else {
- idleObjects.addLast(p);
+ 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(key);
+ }
}
- 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(key);
+ } finally {
+ if (hasBorrowWaiters()) {
+ reuseCapacity();
}
+ updateStatsReturn(activeTime);
}
-
- if (hasBorrowWaiters()) {
- reuseCapacity();
- }
-
- updateStatsReturn(activeTime);
}
@@ -577,11 +566,11 @@ public class GenericKeyedObjectPool<K,T>
* under the given key
*/
@Override
- public void invalidateObject(K key, T obj) throws Exception {
+ public void invalidateObject(final K key, final T obj) throws Exception {
- ObjectDeque<T> objectDeque = poolMap.get(key);
+ final ObjectDeque<T> objectDeque = poolMap.get(key);
- PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
+ final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));
if (p == null) {
throw new IllegalStateException(
"Object not currently part of this pool");
@@ -618,7 +607,7 @@ public class GenericKeyedObjectPool<K,T>
*/
@Override
public void clear() {
- Iterator<K> iter = poolMap.keySet().iterator();
+ final Iterator<K> iter = poolMap.keySet().iterator();
while (iter.hasNext()) {
clear(iter.next());
@@ -635,12 +624,12 @@ public class GenericKeyedObjectPool<K,T>
* @param key the key to clear
*/
@Override
- public void clear(K key) {
+ public void clear(final K key) {
- ObjectDeque<T> objectDeque = register(key);
+ final ObjectDeque<T> objectDeque = register(key);
try {
- LinkedBlockingDeque<PooledObject<T>> idleObjects =
+ final LinkedBlockingDeque<PooledObject<T>> idleObjects =
objectDeque.getIdleObjects();
PooledObject<T> p = idleObjects.poll();
@@ -648,7 +637,7 @@ public class GenericKeyedObjectPool<K,T>
while (p != null) {
try {
destroy(key, p, true);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
p = idleObjects.poll();
@@ -667,7 +656,7 @@ public class GenericKeyedObjectPool<K,T>
@Override
public int getNumIdle() {
- Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
+ final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
int result = 0;
while (iter.hasNext()) {
@@ -679,7 +668,7 @@ public class GenericKeyedObjectPool<K,T>
@Override
- public int getNumActive(K key) {
+ public int getNumActive(final K key) {
final ObjectDeque<T> objectDeque = poolMap.get(key);
if (objectDeque != null) {
return objectDeque.getAllObjects().size() -
@@ -690,7 +679,7 @@ public class GenericKeyedObjectPool<K,T>
@Override
- public int getNumIdle(K key) {
+ public int getNumIdle(final K key) {
final ObjectDeque<T> objectDeque = poolMap.get(key);
return objectDeque != null ? objectDeque.getIdleObjects().size() : 0;
}
@@ -727,7 +716,7 @@ public class GenericKeyedObjectPool<K,T>
jmxUnregister();
// Release any threads that were waiting for an object
- Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
+ final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
while (iter.hasNext()) {
iter.next().getIdleObjects().interuptTakeWaiters();
}
@@ -747,14 +736,15 @@ public class GenericKeyedObjectPool<K,T>
// build sorted map of idle objects
final Map<PooledObject<T>, K> map = new TreeMap<>();
- for (K k : poolMap.keySet()) {
- ObjectDeque<T> queue = poolMap.get(k);
+ for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
+ final K k = entry.getKey();
+ final ObjectDeque<T> deque = entry.getValue();
// Protect against possible NPE if key has been removed in another
// thread. Not worth locking the keys while this loop completes.
- if (queue != null) {
+ if (deque != null) {
final LinkedBlockingDeque<PooledObject<T>> idleObjects =
- queue.getIdleObjects();
- for (PooledObject<T> p : idleObjects) {
+ deque.getIdleObjects();
+ for (final PooledObject<T> p : idleObjects) {
// each item into the map using the PooledObject object as the
// key. It then gets sorted based on the idle time
map.put(p, k);
@@ -765,22 +755,22 @@ public class GenericKeyedObjectPool<K,T>
// Now iterate created map and kill the first 15% plus one to account
// for zero
int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
- Iterator<Map.Entry<PooledObject<T>, K>> iter =
+ final Iterator<Map.Entry<PooledObject<T>, K>> iter =
map.entrySet().iterator();
while (iter.hasNext() && itemsToRemove > 0) {
- Map.Entry<PooledObject<T>, K> entry = iter.next();
+ final Map.Entry<PooledObject<T>, K> entry = iter.next();
// kind of backwards on naming. In the map, each key is the
// PooledObject because it has the ordering with the timestamp
// value. Each value that the key references is the key of the
// list it belongs to.
- K key = entry.getValue();
- PooledObject<T> p = entry.getKey();
+ final K key = entry.getValue();
+ final PooledObject<T> p = entry.getKey();
// Assume the destruction succeeds
boolean destroyed = true;
try {
destroyed = destroy(key, p, false);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
if (destroyed) {
@@ -809,8 +799,9 @@ public class GenericKeyedObjectPool<K,T>
int maxQueueLength = 0;
LinkedBlockingDeque<PooledObject<T>> mostLoaded = null;
K loadedKey = null;
- for (K k : poolMap.keySet()) {
- final ObjectDeque<T> deque = poolMap.get(k);
+ for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
+ final K k = entry.getKey();
+ final ObjectDeque<T> deque = entry.getValue();
if (deque != null) {
final LinkedBlockingDeque<PooledObject<T>> pool = deque.getIdleObjects();
final int queueLength = pool.getTakeQueueLength();
@@ -826,11 +817,11 @@ public class GenericKeyedObjectPool<K,T>
if (mostLoaded != null) {
register(loadedKey);
try {
- PooledObject<T> p = create(loadedKey);
+ final PooledObject<T> p = create(loadedKey);
if (p != null) {
addIdleObject(loadedKey, p);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
} finally {
deregister(loadedKey);
@@ -846,8 +837,8 @@ public class GenericKeyedObjectPool<K,T>
* {@code false}
*/
private boolean hasBorrowWaiters() {
- for (K k : poolMap.keySet()) {
- final ObjectDeque<T> deque = poolMap.get(k);
+ for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
+ final ObjectDeque<T> deque = entry.getValue();
if (deque != null) {
final LinkedBlockingDeque<PooledObject<T>> pool =
deque.getIdleObjects();
@@ -876,22 +867,22 @@ public class GenericKeyedObjectPool<K,T>
}
PooledObject<T> underTest = null;
- EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
+ final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
synchronized (evictionLock) {
- EvictionConfig evictionConfig = new EvictionConfig(
+ final EvictionConfig evictionConfig = new EvictionConfig(
getMinEvictableIdleTimeMillis(),
getSoftMinEvictableIdleTimeMillis(),
getMinIdlePerKey());
- boolean testWhileIdle = getTestWhileIdle();
+ final boolean testWhileIdle = getTestWhileIdle();
for (int i = 0, m = getNumTests(); i < m; i++) {
if(evictionIterator == null || !evictionIterator.hasNext()) {
if (evictionKeyIterator == null ||
!evictionKeyIterator.hasNext()) {
- List<K> keyCopy = new ArrayList<>();
- Lock readLock = keyLock.readLock();
+ final List<K> keyCopy = new ArrayList<>();
+ final Lock readLock = keyLock.readLock();
readLock.lock();
try {
keyCopy.addAll(poolKeyList);
@@ -902,7 +893,7 @@ public class GenericKeyedObjectPool<K,T>
}
while (evictionKeyIterator.hasNext()) {
evictionKey = evictionKeyIterator.next();
- ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
+ final ObjectDeque<T> objectDeque = poolMap.get(evictionKey);
if (objectDeque == null) {
continue;
}
@@ -923,7 +914,7 @@ public class GenericKeyedObjectPool<K,T>
try {
underTest = evictionIterator.next();
idleObjects = evictionIterator.getIdleObjects();
- } catch (NoSuchElementException nsee) {
+ } catch (final NoSuchElementException nsee) {
// Object was borrowed in another thread
// Don't count this as an eviction test so reduce i;
i--;
@@ -945,7 +936,7 @@ public class GenericKeyedObjectPool<K,T>
try {
evict = evictionPolicy.evict(evictionConfig, underTest,
poolMap.get(evictionKey).getIdleObjects().size());
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// Slightly convoluted as SwallowedExceptionListener uses
// Exception rather than Throwable
PoolUtils.checkRethrow(t);
@@ -963,7 +954,7 @@ public class GenericKeyedObjectPool<K,T>
try {
factory.activateObject(evictionKey, underTest);
active = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
}
@@ -974,7 +965,7 @@ public class GenericKeyedObjectPool<K,T>
} else {
try {
factory.passivateObject(evictionKey, underTest);
- } catch (Exception e) {
+ } catch (final Exception e) {
destroy(evictionKey, underTest, true);
destroyedByEvictorCount.incrementAndGet();
}
@@ -999,15 +990,20 @@ public class GenericKeyedObjectPool<K,T>
*
* @throws Exception If the objection creation fails
*/
- private PooledObject<T> create(K key) throws Exception {
+ private PooledObject<T> create(final K key) throws Exception {
int maxTotalPerKeySave = getMaxTotalPerKey(); // Per key
- int maxTotal = getMaxTotal(); // All keys
+ if (maxTotalPerKeySave < 0) {
+ maxTotalPerKeySave = Integer.MAX_VALUE;
+ }
+ final int maxTotal = getMaxTotal(); // All keys
+
+ final ObjectDeque<T> objectDeque = poolMap.get(key);
// Check against the overall limit
boolean loop = true;
while (loop) {
- int newNumTotal = numTotal.incrementAndGet();
+ final int newNumTotal = numTotal.incrementAndGet();
if (maxTotal > -1 && newNumTotal > maxTotal) {
numTotal.decrementAndGet();
if (getNumIdle() == 0) {
@@ -1019,25 +1015,58 @@ public class GenericKeyedObjectPool<K,T>
}
}
- ObjectDeque<T> objectDeque = poolMap.get(key);
- long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
+ // Flag that indicates if create should:
+ // - TRUE: call the factory to create an object
+ // - FALSE: return null
+ // - null: loop and re-test the condition that determines whether to
+ // call the factory
+ Boolean create = null;
+ while (create == null) {
+ synchronized (objectDeque.makeObjectCountLock) {
+ final long newCreateCount = objectDeque.getCreateCount().incrementAndGet();
+ // Check against the per key limit
+ if (newCreateCount > maxTotalPerKeySave) {
+ // The key is currently at capacity or in the process of
+ // making enough new objects to take it to capacity.
+ objectDeque.getCreateCount().decrementAndGet();
+ if (objectDeque.makeObjectCount == 0) {
+ // There are no makeObject() calls in progress for this
+ // key so the key is at capacity. Do not attempt to
+ // create a new object. Return and wait for an object to
+ // be returned.
+ create = Boolean.FALSE;
+ } else {
+ // There are makeObject() calls in progress that might
+ // bring the pool to capacity. Those calls might also
+ // fail so wait until they complete and then re-test if
+ // the pool is at capacity or not.
+ objectDeque.makeObjectCountLock.wait();
+ }
+ } else {
+ // The pool is not at capacity. Create a new object.
+ objectDeque.makeObjectCount++;
+ create = Boolean.TRUE;
+ }
+ }
+ }
- // Check against the per key limit
- if (maxTotalPerKeySave > -1 && newCreateCount > maxTotalPerKeySave ||
- newCreateCount > Integer.MAX_VALUE) {
+ if (!create.booleanValue()) {
numTotal.decrementAndGet();
- objectDeque.getCreateCount().decrementAndGet();
return null;
}
-
PooledObject<T> p = null;
try {
p = factory.makeObject(key);
- } catch (Exception e) {
+ } catch (final Exception e) {
numTotal.decrementAndGet();
objectDeque.getCreateCount().decrementAndGet();
throw e;
+ } finally {
+ synchronized (objectDeque.makeObjectCountLock) {
+ objectDeque.makeObjectCount--;
+ objectDeque.makeObjectCountLock.notifyAll();
+ }
}
createdCount.incrementAndGet();
@@ -1055,13 +1084,13 @@ public class GenericKeyedObjectPool<K,T>
* @return {@code true} if the object was destroyed, otherwise {@code false}
* @throws Exception If the object destruction failed
*/
- private boolean destroy(K key, PooledObject<T> toDestroy, boolean always)
+ private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always)
throws Exception {
- ObjectDeque<T> objectDeque = register(key);
+ final ObjectDeque<T> objectDeque = register(key);
try {
- boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy);
+ final boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy);
if (isIdle || always) {
objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject()));
@@ -1094,7 +1123,7 @@ public class GenericKeyedObjectPool<K,T>
* method returns without throwing an exception then it will never
* return null.
*/
- private ObjectDeque<T> register(K k) {
+ private ObjectDeque<T> register(final K k) {
Lock lock = keyLock.readLock();
ObjectDeque<T> objectDeque = null;
try {
@@ -1133,14 +1162,14 @@ public class GenericKeyedObjectPool<K,T>
*
* @param k The key to de-register
*/
- private void deregister(K k) {
+ private void deregister(final K k) {
ObjectDeque<T> objectDeque;
objectDeque = poolMap.get(k);
- long numInterested = objectDeque.getNumInterested().decrementAndGet();
+ final long numInterested = objectDeque.getNumInterested().decrementAndGet();
if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
// Potential to remove key
- Lock writeLock = keyLock.writeLock();
+ final Lock writeLock = keyLock.writeLock();
writeLock.lock();
try {
if (objectDeque.getCreateCount().get() == 0 &&
@@ -1159,12 +1188,12 @@ public class GenericKeyedObjectPool<K,T>
@Override
void ensureMinIdle() throws Exception {
- int minIdlePerKeySave = getMinIdlePerKey();
+ final int minIdlePerKeySave = getMinIdlePerKey();
if (minIdlePerKeySave < 1) {
return;
}
- for (K k : poolMap.keySet()) {
+ for (final K k : poolMap.keySet()) {
ensureMinIdle(k);
}
}
@@ -1177,9 +1206,9 @@ public class GenericKeyedObjectPool<K,T>
*
* @throws Exception If a new object is required and cannot be created
*/
- private void ensureMinIdle(K key) throws Exception {
+ private void ensureMinIdle(final K key) throws Exception {
// Calculate current pool objects
- ObjectDeque<T> objectDeque = poolMap.get(key);
+ final ObjectDeque<T> objectDeque = poolMap.get(key);
// objectDeque == null is OK here. It is handled correctly by both
// methods called below.
@@ -1189,7 +1218,7 @@ public class GenericKeyedObjectPool<K,T>
// as a loop limit and a second time inside the loop
// to stop when another thread already returned the
// needed objects
- int deficit = calculateDeficit(objectDeque);
+ final int deficit = calculateDeficit(objectDeque);
for (int i = 0; i < deficit && calculateDeficit(objectDeque) > 0; i++) {
addObject(key);
@@ -1208,11 +1237,11 @@ public class GenericKeyedObjectPool<K,T>
* fails.
*/
@Override
- public void addObject(K key) throws Exception {
+ public void addObject(final K key) throws Exception {
assertOpen();
register(key);
try {
- PooledObject<T> p = create(key);
+ final PooledObject<T> p = create(key);
addIdleObject(key, p);
} finally {
deregister(key);
@@ -1227,11 +1256,11 @@ public class GenericKeyedObjectPool<K,T>
*
* @throws Exception If the associated factory fails to passivate the object
*/
- private void addIdleObject(K key, PooledObject<T> p) throws Exception {
+ private void addIdleObject(final K key, final PooledObject<T> p) throws Exception {
if (p != null) {
factory.passivateObject(key, p);
- LinkedBlockingDeque<PooledObject<T>> idleObjects =
+ final LinkedBlockingDeque<PooledObject<T>> idleObjects =
poolMap.get(key).getIdleObjects();
if (getLifo()) {
idleObjects.addFirst(p);
@@ -1249,8 +1278,8 @@ public class GenericKeyedObjectPool<K,T>
*
* @throws Exception If the associated factory throws an exception
*/
- public void preparePool(K key) throws Exception {
- int minIdlePerKeySave = getMinIdlePerKey();
+ public void preparePool(final K key) throws Exception {
+ final int minIdlePerKeySave = getMinIdlePerKey();
if (minIdlePerKeySave < 1) {
return;
}
@@ -1264,8 +1293,8 @@ public class GenericKeyedObjectPool<K,T>
* @return The number of objects to test for validity
*/
private int getNumTests() {
- int totalIdle = getNumIdle();
- int numTests = getNumTestsPerEvictionRun();
+ final int totalIdle = getNumIdle();
+ final int numTests = getNumTestsPerEvictionRun();
if (numTests >= 0) {
return Math.min(numTests, totalIdle);
}
@@ -1281,15 +1310,15 @@ public class GenericKeyedObjectPool<K,T>
*
* @return The number of new objects to create
*/
- private int calculateDeficit(ObjectDeque<T> objectDeque) {
+ private int calculateDeficit(final ObjectDeque<T> objectDeque) {
if (objectDeque == null) {
return getMinIdlePerKey();
}
// Used more than once so keep a local copy so the value is consistent
- int maxTotal = getMaxTotal();
- int maxTotalPerKeySave = getMaxTotalPerKey();
+ final int maxTotal = getMaxTotal();
+ final int maxTotalPerKeySave = getMaxTotalPerKey();
int objectDefecit = 0;
@@ -1297,14 +1326,14 @@ public class GenericKeyedObjectPool<K,T>
// the number of pooled objects < maxTotalPerKey();
objectDefecit = getMinIdlePerKey() - objectDeque.getIdleObjects().size();
if (maxTotalPerKeySave > 0) {
- int growLimit = Math.max(0,
+ final int growLimit = Math.max(0,
maxTotalPerKeySave - objectDeque.getIdleObjects().size());
objectDefecit = Math.min(objectDefecit, growLimit);
}
// Take the maxTotal limit into account
if (maxTotal > 0) {
- int growLimit = Math.max(0, maxTotal - getNumActive() - getNumIdle());
+ final int growLimit = Math.max(0, maxTotal - getNumActive() - getNumIdle());
objectDefecit = Math.min(objectDefecit, growLimit);
}
@@ -1316,14 +1345,14 @@ public class GenericKeyedObjectPool<K,T>
@Override
public Map<String,Integer> getNumActivePerKey() {
- HashMap<String,Integer> result = new HashMap<>();
+ final HashMap<String,Integer> result = new HashMap<>();
- Iterator<Entry<K,ObjectDeque<T>>> iter = poolMap.entrySet().iterator();
+ final Iterator<Entry<K,ObjectDeque<T>>> iter = poolMap.entrySet().iterator();
while (iter.hasNext()) {
- Entry<K,ObjectDeque<T>> entry = iter.next();
+ final Entry<K,ObjectDeque<T>> entry = iter.next();
if (entry != null) {
- K key = entry.getKey();
- ObjectDeque<T> objectDequeue = entry.getValue();
+ final K key = entry.getKey();
+ final ObjectDeque<T> objectDequeue = entry.getValue();
if (key != null && objectDequeue != null) {
result.put(key.toString(), Integer.valueOf(
objectDequeue.getAllObjects().size() -
@@ -1347,7 +1376,7 @@ public class GenericKeyedObjectPool<K,T>
int result = 0;
if (getBlockWhenExhausted()) {
- Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
+ final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator();
while (iter.hasNext()) {
// Assume no overflow
@@ -1368,16 +1397,17 @@ public class GenericKeyedObjectPool<K,T>
*/
@Override
public Map<String,Integer> getNumWaitersByKey() {
- Map<String,Integer> result = new HashMap<>();
+ final Map<String,Integer> result = new HashMap<>();
- for (K key : poolMap.keySet()) {
- ObjectDeque<T> queue = poolMap.get(key);
- if (queue != null) {
+ for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
+ final K k = entry.getKey();
+ final ObjectDeque<T> deque = entry.getValue();
+ if (deque != null) {
if (getBlockWhenExhausted()) {
- result.put(key.toString(), Integer.valueOf(
- queue.getIdleObjects().getTakeQueueLength()));
+ result.put(k.toString(), Integer.valueOf(
+ deque.getIdleObjects().getTakeQueueLength()));
} else {
- result.put(key.toString(), Integer.valueOf(0));
+ result.put(k.toString(), Integer.valueOf(0));
}
}
}
@@ -1397,16 +1427,17 @@ public class GenericKeyedObjectPool<K,T>
*/
@Override
public Map<String,List<DefaultPooledObjectInfo>> listAllObjects() {
- Map<String,List<DefaultPooledObjectInfo>> result =
+ final Map<String,List<DefaultPooledObjectInfo>> result =
new HashMap<>();
- for (K key : poolMap.keySet()) {
- ObjectDeque<T> queue = poolMap.get(key);
- if (queue != null) {
- List<DefaultPooledObjectInfo> list =
+ for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) {
+ final K k = entry.getKey();
+ final ObjectDeque<T> deque = entry.getValue();
+ if (deque != null) {
+ final List<DefaultPooledObjectInfo> list =
new ArrayList<>();
- result.put(key.toString(), list);
- for (PooledObject<T> p : queue.getAllObjects().values()) {
+ result.put(k.toString(), list);
+ for (final PooledObject<T> p : deque.getAllObjects().values()) {
list.add(new DefaultPooledObjectInfo(p));
}
}
@@ -1430,6 +1461,9 @@ public class GenericKeyedObjectPool<K,T>
*/
private final AtomicInteger createCount = new AtomicInteger(0);
+ private long makeObjectCount = 0;
+ private final Object makeObjectCountLock = new Object();
+
/*
* The map is keyed on pooled instances, wrapped to ensure that
* they work properly as keys.
@@ -1450,7 +1484,7 @@ public class GenericKeyedObjectPool<K,T>
* @param fairness true means client threads waiting to borrow / return instances
* will be served as if waiting in a FIFO queue.
*/
- public ObjectDeque(boolean fairness) {
+ public ObjectDeque(final boolean fairness) {
idleObjects = new LinkedBlockingDeque<>(fairness);
}
@@ -1493,7 +1527,7 @@ public class GenericKeyedObjectPool<K,T>
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
+ final StringBuilder builder = new StringBuilder();
builder.append("ObjectDeque [idleObjects=");
builder.append(idleObjects);
builder.append(", createCount=");
@@ -1551,7 +1585,7 @@ public class GenericKeyedObjectPool<K,T>
"org.apache.tomcat.dbcp.pool2:type=GenericKeyedObjectPool,name=";
@Override
- protected void toStringAppendFields(StringBuilder builder) {
+ protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", maxIdlePerKey=");
builder.append(maxIdlePerKey);
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java?rev=1743698&r1=1743697&r2=1743698&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java Fri May 13 16:48:56 2016
@@ -89,7 +89,7 @@ public class GenericKeyedObjectPoolConfi
*
* @see GenericKeyedObjectPool#setMaxTotal(int)
*/
- public void setMaxTotal(int maxTotal) {
+ public void setMaxTotal(final int maxTotal) {
this.maxTotal = maxTotal;
}
@@ -115,7 +115,7 @@ public class GenericKeyedObjectPoolConfi
*
* @see GenericKeyedObjectPool#setMaxTotalPerKey(int)
*/
- public void setMaxTotalPerKey(int maxTotalPerKey) {
+ public void setMaxTotalPerKey(final int maxTotalPerKey) {
this.maxTotalPerKey = maxTotalPerKey;
}
@@ -141,7 +141,7 @@ public class GenericKeyedObjectPoolConfi
*
* @see GenericKeyedObjectPool#setMinIdlePerKey(int)
*/
- public void setMinIdlePerKey(int minIdlePerKey) {
+ public void setMinIdlePerKey(final int minIdlePerKey) {
this.minIdlePerKey = minIdlePerKey;
}
@@ -167,7 +167,7 @@ public class GenericKeyedObjectPoolConfi
*
* @see GenericKeyedObjectPool#setMaxIdlePerKey(int)
*/
- public void setMaxIdlePerKey(int maxIdlePerKey) {
+ public void setMaxIdlePerKey(final int maxIdlePerKey) {
this.maxIdlePerKey = maxIdlePerKey;
}
@@ -175,13 +175,13 @@ public class GenericKeyedObjectPoolConfi
public GenericKeyedObjectPoolConfig clone() {
try {
return (GenericKeyedObjectPoolConfig) super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
@Override
- protected void toStringAppendFields(StringBuilder builder) {
+ protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", minIdlePerKey=");
builder.append(minIdlePerKey);
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java?rev=1743698&r1=1743697&r2=1743698&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java Fri May 13 16:48:56 2016
@@ -83,7 +83,7 @@ public class GenericObjectPool<T> extend
* @param factory The object factory to be used to create object instances
* used by this pool
*/
- public GenericObjectPool(PooledObjectFactory<T> factory) {
+ public GenericObjectPool(final PooledObjectFactory<T> factory) {
this(factory, new GenericObjectPoolConfig());
}
@@ -98,8 +98,8 @@ public class GenericObjectPool<T> extend
* the configuration object will not be reflected in the
* pool.
*/
- public GenericObjectPool(PooledObjectFactory<T> factory,
- GenericObjectPoolConfig config) {
+ public GenericObjectPool(final PooledObjectFactory<T> factory,
+ final GenericObjectPoolConfig config) {
super(config, ONAME_BASE, config.getJmxNamePrefix());
@@ -129,8 +129,8 @@ public class GenericObjectPool<T> extend
* @param abandonedConfig Configuration for abandoned object identification
* and removal. The configuration is used by value.
*/
- public GenericObjectPool(PooledObjectFactory<T> factory,
- GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) {
+ public GenericObjectPool(final PooledObjectFactory<T> factory,
+ final GenericObjectPoolConfig config, final AbandonedConfig abandonedConfig) {
this(factory, config);
setAbandonedConfig(abandonedConfig);
}
@@ -170,7 +170,7 @@ public class GenericObjectPool<T> extend
*
* @see #getMaxIdle
*/
- public void setMaxIdle(int maxIdle) {
+ public void setMaxIdle(final int maxIdle) {
this.maxIdle = maxIdle;
}
@@ -191,7 +191,7 @@ public class GenericObjectPool<T> extend
* @see #getMaxIdle()
* @see #getTimeBetweenEvictionRunsMillis()
*/
- public void setMinIdle(int minIdle) {
+ public void setMinIdle(final int minIdle) {
this.minIdle = minIdle;
}
@@ -213,7 +213,7 @@ public class GenericObjectPool<T> extend
*/
@Override
public int getMinIdle() {
- int maxIdleSave = getMaxIdle();
+ final int maxIdleSave = getMaxIdle();
if (this.minIdle > maxIdleSave) {
return maxIdleSave;
}
@@ -241,7 +241,7 @@ public class GenericObjectPool<T> extend
*/
@Override
public boolean getLogAbandoned() {
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
return ac != null && ac.getLogAbandoned();
}
@@ -256,7 +256,7 @@ public class GenericObjectPool<T> extend
*/
@Override
public boolean getRemoveAbandonedOnBorrow() {
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
return ac != null && ac.getRemoveAbandonedOnBorrow();
}
@@ -270,7 +270,7 @@ public class GenericObjectPool<T> extend
*/
@Override
public boolean getRemoveAbandonedOnMaintenance() {
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
return ac != null && ac.getRemoveAbandonedOnMaintenance();
}
@@ -285,7 +285,7 @@ public class GenericObjectPool<T> extend
*/
@Override
public int getRemoveAbandonedTimeout() {
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
}
@@ -297,7 +297,7 @@ public class GenericObjectPool<T> extend
*
* @see GenericObjectPoolConfig
*/
- public void setConfig(GenericObjectPoolConfig conf) {
+ public void setConfig(final GenericObjectPoolConfig conf) {
setLifo(conf.getLifo());
setMaxIdle(conf.getMaxIdle());
setMinIdle(conf.getMinIdle());
@@ -324,7 +324,7 @@ public class GenericObjectPool<T> extend
*
* @see AbandonedConfig
*/
- public void setAbandonedConfig(AbandonedConfig abandonedConfig) {
+ public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
if (abandonedConfig == null) {
this.abandonedConfig = null;
} else {
@@ -404,10 +404,10 @@ public class GenericObjectPool<T> extend
* @throws Exception if an object instance cannot be returned due to an
* error
*/
- public T borrowObject(long borrowMaxWaitMillis) throws Exception {
+ public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
assertOpen();
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
(getNumIdle() < 2) &&
(getNumActive() > getMaxTotal() - 3) ) {
@@ -418,21 +418,21 @@ public class GenericObjectPool<T> extend
// Get local copy of current config so it is consistent for entire
// method execution
- boolean blockWhenExhausted = getBlockWhenExhausted();
+ final boolean blockWhenExhausted = getBlockWhenExhausted();
boolean create;
- long waitTime = System.currentTimeMillis();
+ final long waitTime = System.currentTimeMillis();
while (p == null) {
create = false;
- if (blockWhenExhausted) {
- p = idleObjects.pollFirst();
- if (p == null) {
- p = create();
- if (p != null) {
- create = true;
- }
+ p = idleObjects.pollFirst();
+ if (p == null) {
+ p = create();
+ if (p != null) {
+ create = true;
}
+ }
+ if (blockWhenExhausted) {
if (p == null) {
if (borrowMaxWaitMillis < 0) {
p = idleObjects.takeFirst();
@@ -445,37 +445,27 @@ public class GenericObjectPool<T> extend
throw new NoSuchElementException(
"Timeout waiting for idle object");
}
- if (!p.allocate()) {
- p = null;
- }
} else {
- p = idleObjects.pollFirst();
- if (p == null) {
- p = create();
- if (p != null) {
- create = true;
- }
- }
if (p == null) {
throw new NoSuchElementException("Pool exhausted");
}
- if (!p.allocate()) {
- p = null;
- }
+ }
+ if (!p.allocate()) {
+ p = null;
}
if (p != null) {
try {
factory.activateObject(p);
- } catch (Exception e) {
+ } catch (final Exception e) {
try {
destroy(p);
- } catch (Exception e1) {
+ } catch (final Exception e1) {
// Ignore - activation failure is more important
}
p = null;
if (create) {
- NoSuchElementException nsee = new NoSuchElementException(
+ final NoSuchElementException nsee = new NoSuchElementException(
"Unable to activate object");
nsee.initCause(e);
throw nsee;
@@ -486,7 +476,7 @@ public class GenericObjectPool<T> extend
Throwable validationThrowable = null;
try {
validate = factory.validateObject(p);
- } catch (Throwable t) {
+ } catch (final Throwable t) {
PoolUtils.checkRethrow(t);
validationThrowable = t;
}
@@ -494,12 +484,12 @@ public class GenericObjectPool<T> extend
try {
destroy(p);
destroyedByBorrowValidationCount.incrementAndGet();
- } catch (Exception e) {
+ } catch (final Exception e) {
// Ignore - validation failure is more important
}
p = null;
if (create) {
- NoSuchElementException nsee = new NoSuchElementException(
+ final NoSuchElementException nsee = new NoSuchElementException(
"Unable to validate object");
nsee.initCause(validationThrowable);
throw nsee;
@@ -530,8 +520,8 @@ public class GenericObjectPool<T> extend
* {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.
*/
@Override
- public void returnObject(T obj) {
- PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
+ public void returnObject(final T obj) {
+ final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
if (p == null) {
if (!isAbandonedConfig()) {
@@ -550,18 +540,18 @@ public class GenericObjectPool<T> extend
p.markReturning(); // Keep from being marked abandoned
}
- long activeTime = p.getActiveTimeMillis();
+ final long activeTime = p.getActiveTimeMillis();
if (getTestOnReturn()) {
if (!factory.validateObject(p)) {
try {
destroy(p);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
@@ -571,16 +561,16 @@ public class GenericObjectPool<T> extend
try {
factory.passivateObject(p);
- } catch (Exception e1) {
+ } catch (final Exception e1) {
swallowException(e1);
try {
destroy(p);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
@@ -592,11 +582,11 @@ public class GenericObjectPool<T> extend
"Object has already been returned to this pool or is invalid");
}
- int maxIdleSave = getMaxIdle();
+ final int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
try {
destroy(p);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
} else {
@@ -626,8 +616,8 @@ public class GenericObjectPool<T> extend
* @throws IllegalStateException if obj does not belong to this pool
*/
@Override
- public void invalidateObject(T obj) throws Exception {
- PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
+ public void invalidateObject(final T obj) throws Exception {
+ final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
if (p == null) {
if (isAbandonedConfig()) {
return;
@@ -668,7 +658,7 @@ public class GenericObjectPool<T> extend
while (p != null) {
try {
destroy(p);
- } catch (Exception e) {
+ } catch (final Exception e) {
swallowException(e);
}
p = idleObjects.poll();
@@ -732,15 +722,15 @@ public class GenericObjectPool<T> extend
if (idleObjects.size() > 0) {
PooledObject<T> underTest = null;
- EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
+ final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
synchronized (evictionLock) {
- EvictionConfig evictionConfig = new EvictionConfig(
+ final EvictionConfig evictionConfig = new EvictionConfig(
getMinEvictableIdleTimeMillis(),
getSoftMinEvictableIdleTimeMillis(),
getMinIdle());
- boolean testWhileIdle = getTestWhileIdle();
+ final boolean testWhileIdle = getTestWhileIdle();
for (int i = 0, m = getNumTests(); i < m; i++) {
if (evictionIterator == null || !evictionIterator.hasNext()) {
@@ -753,7 +743,7 @@ public class GenericObjectPool<T> extend
try {
underTest = evictionIterator.next();
- } catch (NoSuchElementException nsee) {
+ } catch (final NoSuchElementException nsee) {
// Object was borrowed in another thread
// Don't count this as an eviction test so reduce i;
i--;
@@ -775,7 +765,7 @@ public class GenericObjectPool<T> extend
try {
evict = evictionPolicy.evict(evictionConfig, underTest,
idleObjects.size());
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// Slightly convoluted as SwallowedExceptionListener uses
// Exception rather than Throwable
PoolUtils.checkRethrow(t);
@@ -793,7 +783,7 @@ public class GenericObjectPool<T> extend
try {
factory.activateObject(underTest);
active = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
@@ -804,7 +794,7 @@ public class GenericObjectPool<T> extend
} else {
try {
factory.passivateObject(underTest);
- } catch (Exception e) {
+ } catch (final Exception e) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
@@ -819,7 +809,7 @@ public class GenericObjectPool<T> extend
}
}
}
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
removeAbandoned(ac);
}
@@ -851,10 +841,45 @@ public class GenericObjectPool<T> extend
*/
private PooledObject<T> create() throws Exception {
int localMaxTotal = getMaxTotal();
- long newCreateCount = createCount.incrementAndGet();
- if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
- newCreateCount > Integer.MAX_VALUE) {
- createCount.decrementAndGet();
+ // This simplifies the code later in this method
+ if (localMaxTotal < 0) {
+ localMaxTotal = Integer.MAX_VALUE;
+ }
+
+ // Flag that indicates if create should:
+ // - TRUE: call the factory to create an object
+ // - FALSE: return null
+ // - null: loop and re-test the condition that determines whether to
+ // call the factory
+ Boolean create = null;
+ while (create == null) {
+ synchronized (makeObjectCountLock) {
+ final long newCreateCount = createCount.incrementAndGet();
+ if (newCreateCount > localMaxTotal) {
+ // The pool is currently at capacity or in the process of
+ // making enough new objects to take it to capacity.
+ createCount.decrementAndGet();
+ if (makeObjectCount == 0) {
+ // There are no makeObject() calls in progress so the
+ // pool is at capacity. Do not attempt to create a new
+ // object. Return and wait for an object to be returned
+ create = Boolean.FALSE;
+ } else {
+ // There are makeObject() calls in progress that might
+ // bring the pool to capacity. Those calls might also
+ // fail so wait until they complete and then re-test if
+ // the pool is at capacity or not.
+ makeObjectCountLock.wait();
+ }
+ } else {
+ // The pool is not at capacity. Create a new object.
+ makeObjectCount++;
+ create = Boolean.TRUE;
+ }
+ }
+ }
+
+ if (!create.booleanValue()) {
return null;
}
@@ -864,9 +889,14 @@ public class GenericObjectPool<T> extend
} catch (Exception e) {
createCount.decrementAndGet();
throw e;
+ } finally {
+ synchronized (makeObjectCountLock) {
+ makeObjectCount--;
+ makeObjectCountLock.notifyAll();
+ }
}
- AbandonedConfig ac = this.abandonedConfig;
+ final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getLogAbandoned()) {
p.setLogAbandoned(true);
}
@@ -879,17 +909,17 @@ public class GenericObjectPool<T> extend
/**
* Destroys a wrapped pooled object.
*
- * @param toDestory The wrapped pooled object to destroy
+ * @param toDestroy The wrapped pooled object to destroy
*
* @throws Exception If the factory fails to destroy the pooled object
* cleanly
*/
- private void destroy(PooledObject<T> toDestory) throws Exception {
- toDestory.invalidate();
- idleObjects.remove(toDestory);
- allObjects.remove(new IdentityWrapper<>(toDestory.getObject()));
+ private void destroy(final PooledObject<T> toDestroy) throws Exception {
+ toDestroy.invalidate();
+ idleObjects.remove(toDestroy);
+ allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
try {
- factory.destroyObject(toDestory);
+ factory.destroyObject(toDestroy);
} finally {
destroyedCount.incrementAndGet();
createCount.decrementAndGet();
@@ -913,13 +943,13 @@ public class GenericObjectPool<T> extend
* @param always true means create instances even if the pool has no threads waiting
* @throws Exception if the factory's makeObject throws
*/
- private void ensureIdle(int idleCount, boolean always) throws Exception {
+ private void ensureIdle(final int idleCount, final boolean always) throws Exception {
if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
return;
}
while (idleObjects.size() < idleCount) {
- PooledObject<T> p = create();
+ final PooledObject<T> p = create();
if (p == null) {
// Can't create objects, no reason to think another call to
// create will work. Give up.
@@ -953,7 +983,7 @@ public class GenericObjectPool<T> extend
throw new IllegalStateException(
"Cannot add objects without a factory.");
}
- PooledObject<T> p = create();
+ final PooledObject<T> p = create();
addIdleObject(p);
}
@@ -966,7 +996,7 @@ public class GenericObjectPool<T> extend
*
* @throws Exception If the factory fails to passivate the object
*/
- private void addIdleObject(PooledObject<T> p) throws Exception {
+ private void addIdleObject(final PooledObject<T> p) throws Exception {
if (p != null) {
factory.passivateObject(p);
if (getLifo()) {
@@ -984,7 +1014,7 @@ public class GenericObjectPool<T> extend
* @return The number of objects to test for validity
*/
private int getNumTests() {
- int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
+ final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
if (numTestsPerEvictionRun >= 0) {
return Math.min(numTestsPerEvictionRun, idleObjects.size());
}
@@ -998,15 +1028,15 @@ public class GenericObjectPool<T> extend
*
* @param ac The configuration to use to identify abandoned objects
*/
- private void removeAbandoned(AbandonedConfig ac) {
+ private void removeAbandoned(final AbandonedConfig ac) {
// Generate a list of abandoned objects to remove
final long now = System.currentTimeMillis();
final long timeout =
now - (ac.getRemoveAbandonedTimeout() * 1000L);
- ArrayList<PooledObject<T>> remove = new ArrayList<>();
- Iterator<PooledObject<T>> it = allObjects.values().iterator();
+ final ArrayList<PooledObject<T>> remove = new ArrayList<>();
+ final Iterator<PooledObject<T>> it = allObjects.values().iterator();
while (it.hasNext()) {
- PooledObject<T> pooledObject = it.next();
+ final PooledObject<T> pooledObject = it.next();
synchronized (pooledObject) {
if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
pooledObject.getLastUsedTime() <= timeout) {
@@ -1017,15 +1047,15 @@ public class GenericObjectPool<T> extend
}
// Now remove the abandoned objects
- Iterator<PooledObject<T>> itr = remove.iterator();
+ final Iterator<PooledObject<T>> itr = remove.iterator();
while (itr.hasNext()) {
- PooledObject<T> pooledObject = itr.next();
+ final PooledObject<T> pooledObject = itr.next();
if (ac.getLogAbandoned()) {
pooledObject.printStackTrace(ac.getLogWriter());
}
try {
invalidateObject(pooledObject.getObject());
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
}
@@ -1035,10 +1065,10 @@ public class GenericObjectPool<T> extend
//--- Usage tracking support -----------------------------------------------
@Override
- public void use(T pooledObject) {
- AbandonedConfig ac = this.abandonedConfig;
+ public void use(final T pooledObject) {
+ final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getUseUsageTracking()) {
- PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
+ final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
wrapper.use();
}
}
@@ -1074,10 +1104,10 @@ public class GenericObjectPool<T> extend
public String getFactoryType() {
// Not thread safe. Accept that there may be multiple evaluations.
if (factoryType == null) {
- StringBuilder result = new StringBuilder();
+ final StringBuilder result = new StringBuilder();
result.append(factory.getClass().getName());
result.append('<');
- Class<?> pooledObjectType =
+ final Class<?> pooledObjectType =
PoolImplUtils.getFactoryType(factory.getClass());
result.append(pooledObjectType.getName());
result.append('>');
@@ -1099,9 +1129,9 @@ public class GenericObjectPool<T> extend
*/
@Override
public Set<DefaultPooledObjectInfo> listAllObjects() {
- Set<DefaultPooledObjectInfo> result =
+ final Set<DefaultPooledObjectInfo> result =
new HashSet<>(allObjects.size());
- for (PooledObject<T> p : allObjects.values()) {
+ for (final PooledObject<T> p : allObjects.values()) {
result.add(new DefaultPooledObjectInfo(p));
}
return result;
@@ -1133,6 +1163,8 @@ public class GenericObjectPool<T> extend
* {@link #_maxActive} objects created at any one time.
*/
private final AtomicLong createCount = new AtomicLong(0);
+ private long makeObjectCount = 0;
+ private final Object makeObjectCountLock = new Object();
private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
// JMX specific attributes
@@ -1143,7 +1175,7 @@ public class GenericObjectPool<T> extend
private volatile AbandonedConfig abandonedConfig = null;
@Override
- protected void toStringAppendFields(StringBuilder builder) {
+ protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", factoryType=");
builder.append(factoryType);
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java?rev=1743698&r1=1743697&r2=1743698&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java Fri May 13 16:48:56 2016
@@ -75,7 +75,7 @@ public class GenericObjectPoolConfig ext
*
* @see GenericObjectPool#setMaxTotal(int)
*/
- public void setMaxTotal(int maxTotal) {
+ public void setMaxTotal(final int maxTotal) {
this.maxTotal = maxTotal;
}
@@ -102,7 +102,7 @@ public class GenericObjectPoolConfig ext
*
* @see GenericObjectPool#setMaxIdle(int)
*/
- public void setMaxIdle(int maxIdle) {
+ public void setMaxIdle(final int maxIdle) {
this.maxIdle = maxIdle;
}
@@ -129,7 +129,7 @@ public class GenericObjectPoolConfig ext
*
* @see GenericObjectPool#setMinIdle(int)
*/
- public void setMinIdle(int minIdle) {
+ public void setMinIdle(final int minIdle) {
this.minIdle = minIdle;
}
@@ -137,13 +137,13 @@ public class GenericObjectPoolConfig ext
public GenericObjectPoolConfig clone() {
try {
return (GenericObjectPoolConfig) super.clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
@Override
- protected void toStringAppendFields(StringBuilder builder) {
+ protected void toStringAppendFields(final StringBuilder builder) {
super.toStringAppendFields(builder);
builder.append(", maxTotal=");
builder.append(maxTotal);
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java?rev=1743698&r1=1743697&r2=1743698&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java Fri May 13 16:48:56 2016
@@ -39,7 +39,7 @@ class InterruptibleReentrantLock extends
* @param fairness true means threads should acquire contended locks as if
* waiting in a FIFO queue
*/
- public InterruptibleReentrantLock(boolean fairness) {
+ public InterruptibleReentrantLock(final boolean fairness) {
super(fairness);
}
@@ -48,9 +48,9 @@ class InterruptibleReentrantLock extends
*
* @param condition the condition on which the threads are waiting.
*/
- public void interruptWaiters(Condition condition) {
- Collection<Thread> threads = getWaitingThreads(condition);
- for (Thread thread : threads) {
+ public void interruptWaiters(final Condition condition) {
+ final Collection<Thread> threads = getWaitingThreads(condition);
+ for (final Thread thread : threads) {
thread.interrupt();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org