This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit a3fd9eee952b99974b23f0b328f5fb3f25f79c5e Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri Dec 6 15:43:08 2019 +0000 Merge in Pool 2 changes to 6092f92 (2019-12-06, 2.8.0-SNAPSHOT) --- MERGE.txt | 12 +- .../dbcp/pool2/BaseKeyedPooledObjectFactory.java | 2 + .../apache/tomcat/dbcp/pool2/BaseObjectPool.java | 18 + .../apache/tomcat/dbcp/pool2/KeyedObjectPool.java | 211 ++-- java/org/apache/tomcat/dbcp/pool2/ObjectPool.java | 134 ++- java/org/apache/tomcat/dbcp/pool2/PoolUtils.java | 1270 ++------------------ .../org/apache/tomcat/dbcp/pool2/PooledObject.java | 3 +- .../dbcp/pool2/impl/DefaultEvictionPolicy.java | 2 + .../tomcat/dbcp/pool2/impl/EvictionConfig.java | 1 + .../dbcp/pool2/impl/GenericKeyedObjectPool.java | 78 +- .../tomcat/dbcp/pool2/impl/GenericObjectPool.java | 46 +- .../pool2/impl/InterruptibleReentrantLock.java | 1 + .../dbcp/pool2/impl/LinkedBlockingDeque.java | 4 + .../dbcp/pool2/impl/SoftReferenceObjectPool.java | 3 + webapps/docs/changelog.xml | 4 + 15 files changed, 421 insertions(+), 1368 deletions(-) diff --git a/MERGE.txt b/MERGE.txt index 893ac89..7daec6d 100644 --- a/MERGE.txt +++ b/MERGE.txt @@ -58,15 +58,15 @@ Note: Tomcat's copy of fileupload also includes classes copied manually from DBCP ---- +Pool2 +Sub-tree +src/main/java/org/apache/commons/pool2 +The SHA1 ID for the most recent commit to be merged to Tomcat is: +6092f924b36061353ff92b18c88400ab3bc05327 (2019-12-06) + DBCP2 Sub-tree src/main/java/org/apache/commons/dbcp2 src/main/resources/org/apache/commons/dbcp2 The SHA1 ID for the most recent commit to be merged to Tomcat is: 4813b7f5456c1f4fecc4f701ac731a71f57db249 (2019-08-09) - -Pool2 -Sub-tree -src/main/java/org/apache/commons/pool2 -The SHA1 ID for the most recent commit to be merged to Tomcat is: -796e32d53cc0d870ba0db3a7faf4c5b24ff76f3f (2019-08-01) diff --git a/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java b/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java index 3dd7429..dfbc5a9 100644 --- a/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java +++ b/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java @@ -21,7 +21,9 @@ package org.apache.tomcat.dbcp.pool2; * <p> * All operations defined here are essentially no-op's. * </p> + * <p> * This class is immutable, and therefore thread-safe. + * </p> * * @see KeyedPooledObjectFactory * diff --git a/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java index 29f189a..96d3c00 100644 --- a/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java @@ -22,6 +22,7 @@ package org.apache.tomcat.dbcp.pool2; * indicating it is unsupported or throw {@link UnsupportedOperationException}. * <p> * This class is intended to be thread-safe. + * </p> * * @param <T> Type of element pooled in this pool. * @@ -82,6 +83,23 @@ public abstract class BaseObjectPool<T> extends BaseObject implements ObjectPool } /** + * Calls {@link ObjectPool#addObject()} <code>count</code> + * number of times. + * + * @param count + * the number of idle objects to add. + * @throws Exception + * when {@link ObjectPool#addObject()} fails. + * @since 2.8.0 + */ + @Override + public void addObjects(final int count) throws Exception { + for (int i = 0; i < count; i++) { + addObject(); + } + } + + /** * {@inheritDoc} * <p> * This affects the behavior of <code>isClosed</code> and diff --git a/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java index 4df37d8..df325ed 100644 --- a/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java @@ -17,6 +17,7 @@ package org.apache.tomcat.dbcp.pool2; import java.io.Closeable; +import java.util.Collection; import java.util.NoSuchElementException; /** @@ -66,6 +67,60 @@ import java.util.NoSuchElementException; * @since 2.0 */ public interface KeyedObjectPool<K, V> extends Closeable { + + /** + * Create an object using the {@link KeyedPooledObjectFactory factory} or + * other implementation dependent mechanism, passivate it, and then place it + * in the idle object pool. <code>addObject</code> is useful for + * "pre-loading" a pool with idle objects (Optional operation). + * + * @param key the key a new instance should be added to + * + * @throws Exception + * when {@link KeyedPooledObjectFactory#makeObject} fails. + * @throws IllegalStateException + * after {@link #close} has been called on this pool. + * @throws UnsupportedOperationException + * when this pool cannot add new idle objects. + */ + void addObject(K key) throws Exception, IllegalStateException, + UnsupportedOperationException; + + /** + * Calls {@link KeyedObjectPool#addObject(Object)} with each + * key in <code>keys</code> for <code>count</code> number of times. This has + * the same effect as calling {@link #addObjects(Object, int)} + * for each key in the <code>keys</code> collection. + * + * @param keys + * {@link Collection} of keys to add objects for. + * @param count + * the number of idle objects to add for each <code>key</code>. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when <code>keyedPool</code>, <code>keys</code>, or any value + * in <code>keys</code> is <code>null</code>. + * @see #addObjects(Object, int) + */ + void addObjects(final Collection<K> keys, final int count) throws Exception, IllegalArgumentException; + + /** + * Calls {@link KeyedObjectPool#addObject(Object)} + * <code>key</code> <code>count</code> number of times. + * + * @param key + * the key to add objects for. + * @param count + * the number of idle objects to add for <code>key</code>. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when <code>key</code> is <code>null</code>. + * @since 2.8.0 + */ + void addObjects(final K key, final int count) throws Exception, IllegalArgumentException; + /** * Obtains an instance from this pool for the specified <code>key</code>. * <p> @@ -105,75 +160,50 @@ public interface KeyedObjectPool<K, V> extends Closeable { V borrowObject(K key) throws Exception, NoSuchElementException, IllegalStateException; /** - * Return an instance to the pool. By contract, <code>obj</code> - * <strong>must</strong> have been obtained using - * {@link #borrowObject borrowObject} or a related method as defined in an - * implementation or sub-interface using a <code>key</code> that is - * equivalent to the one used to borrow the instance in the first place. - * - * @param key the key used to obtain the object - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * Clears the pool, removing all pooled instances (optional operation). * - * @throws IllegalStateException - * if an attempt is made to return an object to the pool that - * is in any state other than allocated (i.e. borrowed). - * Attempting to return an object more than once or attempting - * to return an object that was never borrowed from the pool - * will trigger this exception. + * @throws UnsupportedOperationException when this implementation doesn't + * support the operation * - * @throws Exception if an instance cannot be returned to the pool + * @throws Exception if the pool cannot be cleared */ - void returnObject(K key, V obj) throws Exception; + void clear() throws Exception, UnsupportedOperationException; /** - * Invalidates an object from the pool. - * <p> - * By contract, <code>obj</code> <strong>must</strong> have been obtained - * using {@link #borrowObject borrowObject} or a related method as defined - * in an implementation or sub-interface using a <code>key</code> that is - * equivalent to the one used to borrow the <code>Object</code> in the first - * place. - * </p> - * <p> - * This method should be used when an object that has been borrowed is - * determined (due to an exception or other problem) to be invalid. - * </p> + * Clears the specified pool, removing all pooled instances corresponding to + * the given <code>key</code> (optional operation). * - * @param key the key used to obtain the object - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * @param key the key to clear * - * @throws Exception if the instance cannot be invalidated + * @throws UnsupportedOperationException when this implementation doesn't + * support the operation + * + * @throws Exception if the key cannot be cleared */ - void invalidateObject(K key, V obj) throws Exception; + void clear(K key) throws Exception, UnsupportedOperationException; /** - * Create an object using the {@link KeyedPooledObjectFactory factory} or - * other implementation dependent mechanism, passivate it, and then place it - * in the idle object pool. <code>addObject</code> is useful for - * "pre-loading" a pool with idle objects (Optional operation). - * - * @param key the key a new instance should be added to - * - * @throws Exception - * when {@link KeyedPooledObjectFactory#makeObject} fails. - * @throws IllegalStateException - * after {@link #close} has been called on this pool. - * @throws UnsupportedOperationException - * when this pool cannot add new idle objects. + * Close this pool, and free any resources associated with it. + * <p> + * Calling {@link #addObject addObject} or + * {@link #borrowObject borrowObject} after invoking this method on a pool + * will cause them to throw an {@link IllegalStateException}. + * </p> + * <p> + * Implementations should silently fail if not all resources can be freed. + * </p> */ - void addObject(K key) throws Exception, IllegalStateException, - UnsupportedOperationException; + @Override + void close(); /** - * Returns the number of instances corresponding to the given - * <code>key</code> currently idle in this pool. Returns a negative value if - * this information is not available. - * - * @param key the key to query - * @return the number of instances corresponding to the given - * <code>key</code> currently idle in this pool. + * Returns the total number of instances currently borrowed from this pool but + * not yet returned. Returns a negative value if this information is not + * available. + * @return the total number of instances currently borrowed from this pool but + * not yet returned. */ - int getNumIdle(K key); + int getNumActive(); /** * Returns the number of instances currently borrowed from but not yet @@ -194,48 +224,55 @@ public interface KeyedObjectPool<K, V> extends Closeable { int getNumIdle(); /** - * Returns the total number of instances currently borrowed from this pool but - * not yet returned. Returns a negative value if this information is not - * available. - * @return the total number of instances currently borrowed from this pool but - * not yet returned. + * Returns the number of instances corresponding to the given + * <code>key</code> currently idle in this pool. Returns a negative value if + * this information is not available. + * + * @param key the key to query + * @return the number of instances corresponding to the given + * <code>key</code> currently idle in this pool. */ - int getNumActive(); + int getNumIdle(K key); /** - * Clears the pool, removing all pooled instances (optional operation). + * Invalidates an object from the pool. + * <p> + * By contract, <code>obj</code> <strong>must</strong> have been obtained + * using {@link #borrowObject borrowObject} or a related method as defined + * in an implementation or sub-interface using a <code>key</code> that is + * equivalent to the one used to borrow the <code>Object</code> in the first + * place. + * </p> + * <p> + * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + * </p> * - * @throws UnsupportedOperationException when this implementation doesn't - * support the operation + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. * - * @throws Exception if the pool cannot be cleared + * @throws Exception if the instance cannot be invalidated */ - void clear() throws Exception, UnsupportedOperationException; + void invalidateObject(K key, V obj) throws Exception; /** - * Clears the specified pool, removing all pooled instances corresponding to - * the given <code>key</code> (optional operation). + * Return an instance to the pool. By contract, <code>obj</code> + * <strong>must</strong> have been obtained using + * {@link #borrowObject borrowObject} or a related method as defined in an + * implementation or sub-interface using a <code>key</code> that is + * equivalent to the one used to borrow the instance in the first place. * - * @param key the key to clear + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. * - * @throws UnsupportedOperationException when this implementation doesn't - * support the operation + * @throws IllegalStateException + * if an attempt is made to return an object to the pool that + * is in any state other than allocated (i.e. borrowed). + * Attempting to return an object more than once or attempting + * to return an object that was never borrowed from the pool + * will trigger this exception. * - * @throws Exception if the key cannot be cleared - */ - void clear(K key) throws Exception, UnsupportedOperationException; - - /** - * Close this pool, and free any resources associated with it. - * <p> - * Calling {@link #addObject addObject} or - * {@link #borrowObject borrowObject} after invoking this method on a pool - * will cause them to throw an {@link IllegalStateException}. - * </p> - * <p> - * Implementations should silently fail if not all resources can be freed. - * </p> + * @throws Exception if an instance cannot be returned to the pool */ - @Override - void close(); + void returnObject(K key, V obj) throws Exception; } diff --git a/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java index 6303245..22eb12a 100644 --- a/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java @@ -60,6 +60,34 @@ import java.util.NoSuchElementException; public interface ObjectPool<T> extends Closeable { /** + * Creates an object using the {@link PooledObjectFactory factory} or other + * implementation dependent mechanism, passivate it, and then place it in + * the idle object pool. <code>addObject</code> is useful for "pre-loading" + * a pool with idle objects. (Optional operation). + * + * @throws Exception + * when {@link PooledObjectFactory#makeObject} fails. + * @throws IllegalStateException + * after {@link #close} has been called on this pool. + * @throws UnsupportedOperationException + * when this pool cannot add new idle objects. + */ + void addObject() throws Exception, IllegalStateException, + UnsupportedOperationException; + + /** + * Calls {@link ObjectPool#addObject()} <code>count</code> + * number of times. + * + * @param count + * the number of idle objects to add. + * @throws Exception + * when {@link ObjectPool#addObject()} fails. + * @since 2.8.0 + */ + void addObjects(final int count) throws Exception; + + /** * Obtains an instance from this pool. * <p> * Instances returned from this method will have been either newly created @@ -94,56 +122,36 @@ public interface ObjectPool<T> extends Closeable { IllegalStateException; /** - * Returns an instance to the pool. By contract, <code>obj</code> - * <strong>must</strong> have been obtained using {@link #borrowObject()} or - * a related method as defined in an implementation or sub-interface. - * - * @param obj a {@link #borrowObject borrowed} instance to be returned. + * Clears any objects sitting idle in the pool, releasing any associated + * resources (optional operation). Idle objects cleared must be + * {@link PooledObjectFactory#destroyObject(PooledObject)}. * - * @throws IllegalStateException - * if an attempt is made to return an object to the pool that - * is in any state other than allocated (i.e. borrowed). - * Attempting to return an object more than once or attempting - * to return an object that was never borrowed from the pool - * will trigger this exception. + * @throws UnsupportedOperationException + * if this implementation does not support the operation * - * @throws Exception if an instance cannot be returned to the pool + * @throws Exception if the pool cannot be cleared */ - void returnObject(T obj) throws Exception; + void clear() throws Exception, UnsupportedOperationException; /** - * Invalidates an object from the pool. + * Closes this pool, and free any resources associated with it. * <p> - * By contract, <code>obj</code> <strong>must</strong> have been obtained - * using {@link #borrowObject} or a related method as defined in an - * implementation or sub-interface. + * Calling {@link #addObject} or {@link #borrowObject} after invoking this + * method on a pool will cause them to throw an {@link IllegalStateException}. * </p> * <p> - * This method should be used when an object that has been borrowed is - * determined (due to an exception or other problem) to be invalid. + * Implementations should silently fail if not all resources can be freed. * </p> - * - * @param obj a {@link #borrowObject borrowed} instance to be disposed. - * - * @throws Exception if the instance cannot be invalidated */ - void invalidateObject(T obj) throws Exception; + @Override + void close(); /** - * Creates an object using the {@link PooledObjectFactory factory} or other - * implementation dependent mechanism, passivate it, and then place it in - * the idle object pool. <code>addObject</code> is useful for "pre-loading" - * a pool with idle objects. (Optional operation). - * - * @throws Exception - * when {@link PooledObjectFactory#makeObject} fails. - * @throws IllegalStateException - * after {@link #close} has been called on this pool. - * @throws UnsupportedOperationException - * when this pool cannot add new idle objects. + * Returns the number of instances currently borrowed from this pool. Returns + * a negative value if this information is not available. + * @return the number of instances currently borrowed from this pool. */ - void addObject() throws Exception, IllegalStateException, - UnsupportedOperationException; + int getNumActive(); /** * Returns the number of instances currently idle in this pool. This may be @@ -155,34 +163,38 @@ public interface ObjectPool<T> extends Closeable { int getNumIdle(); /** - * Returns the number of instances currently borrowed from this pool. Returns - * a negative value if this information is not available. - * @return the number of instances currently borrowed from this pool. - */ - int getNumActive(); - - /** - * Clears any objects sitting idle in the pool, releasing any associated - * resources (optional operation). Idle objects cleared must be - * {@link PooledObjectFactory#destroyObject(PooledObject)}. + * Invalidates an object from the pool. + * <p> + * By contract, <code>obj</code> <strong>must</strong> have been obtained + * using {@link #borrowObject} or a related method as defined in an + * implementation or sub-interface. + * </p> + * <p> + * This method should be used when an object that has been borrowed is + * determined (due to an exception or other problem) to be invalid. + * </p> * - * @throws UnsupportedOperationException - * if this implementation does not support the operation + * @param obj a {@link #borrowObject borrowed} instance to be disposed. * - * @throws Exception if the pool cannot be cleared + * @throws Exception if the instance cannot be invalidated */ - void clear() throws Exception, UnsupportedOperationException; + void invalidateObject(T obj) throws Exception; /** - * Closes this pool, and free any resources associated with it. - * <p> - * Calling {@link #addObject} or {@link #borrowObject} after invoking this - * method on a pool will cause them to throw an {@link IllegalStateException}. - * </p> - * <p> - * Implementations should silently fail if not all resources can be freed. - * </p> + * Returns an instance to the pool. By contract, <code>obj</code> + * <strong>must</strong> have been obtained using {@link #borrowObject()} or + * a related method as defined in an implementation or sub-interface. + * + * @param obj a {@link #borrowObject borrowed} instance to be returned. + * + * @throws IllegalStateException + * if an attempt is made to return an object to the pool that + * is in any state other than allocated (i.e. borrowed). + * Attempting to return an object more than once or attempting + * to return an object that was never borrowed from the pool + * will trigger this exception. + * + * @throws Exception if an instance cannot be returned to the pool */ - @Override - void close(); + void returnObject(T obj) throws Exception; } diff --git a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java index 2494351..7df2f9a 100644 --- a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java +++ b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java @@ -17,15 +17,12 @@ package org.apache.tomcat.dbcp.pool2; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; /** @@ -36,11 +33,10 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; */ public final class PoolUtils { - private static final String MSG_FACTOR_NEGATIVE = "factor must be positive."; private static final String MSG_MIN_IDLE = "minIdle must be non-negative."; - private static final String MSG_NULL_KEY = "key must not be null."; + public static final String MSG_NULL_KEY = "key must not be null."; private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null."; - private static final String MSG_NULL_KEYS = "keys must not be null."; + public static final String MSG_NULL_KEYS = "keys must not be null."; private static final String MSG_NULL_POOL = "pool must not be null."; /** @@ -220,15 +216,15 @@ public final class PoolUtils { * when {@link ObjectPool#addObject()} fails. * @throws IllegalArgumentException * when <code>pool</code> is <code>null</code>. + * @deprecated Use {@link ObjectPool#addObjects(int)}. */ + @Deprecated public static <T> void prefill(final ObjectPool<T> pool, final int count) throws Exception, IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException(MSG_NULL_POOL); } - for (int i = 0; i < count; i++) { - pool.addObject(); - } + pool.addObjects(count); } /** @@ -248,19 +244,16 @@ public final class PoolUtils { * @throws IllegalArgumentException * when <code>keyedPool</code> or <code>key</code> is * <code>null</code>. + * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}. */ + @Deprecated public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool, final K key, final int count) throws Exception, IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } - if (key == null) { - throw new IllegalArgumentException(MSG_NULL_KEY); - } - for (int i = 0; i < count; i++) { - keyedPool.addObject(key); - } + keyedPool.addObjects(key, count); } /** @@ -283,85 +276,16 @@ public final class PoolUtils { * when <code>keyedPool</code>, <code>keys</code>, or any value * in <code>keys</code> is <code>null</code>. * @see #prefill(KeyedObjectPool, Object, int) + * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}. */ + @Deprecated public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys, final int count) throws Exception, IllegalArgumentException { if (keys == null) { throw new IllegalArgumentException(MSG_NULL_KEYS); } - final Iterator<K> iter = keys.iterator(); - while (iter.hasNext()) { - prefill(keyedPool, iter.next(), count); - } - } - - /** - * Returns a synchronized (thread-safe) ObjectPool backed by the specified - * ObjectPool. - * <p> - * <b>Note:</b> This should not be used on pool implementations that already - * provide proper synchronization such as the pools provided in the Commons - * Pool library. Wrapping a pool that {@link #wait() waits} for poolable - * objects to be returned before allowing another one to be borrowed with - * another layer of synchronization will cause liveliness issues or a - * deadlock. - * </p> - * - * @param pool - * the ObjectPool to be "wrapped" in a synchronized ObjectPool. - * @param <T> the type of objects in the pool - * @return a synchronized view of the specified ObjectPool. - */ - public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) { - if (pool == null) { - throw new IllegalArgumentException(MSG_NULL_POOL); - } - /* - * assert !(pool instanceof GenericObjectPool) : - * "GenericObjectPool is already thread-safe"; assert !(pool instanceof - * SoftReferenceObjectPool) : - * "SoftReferenceObjectPool is already thread-safe"; assert !(pool - * instanceof StackObjectPool) : - * "StackObjectPool is already thread-safe"; assert - * !"org.apache.commons.pool.composite.CompositeObjectPool" - * .equals(pool.getClass().getName()) : - * "CompositeObjectPools are already thread-safe"; - */ - return new SynchronizedObjectPool<>(pool); - } - - /** - * Returns a synchronized (thread-safe) KeyedObjectPool backed by the - * specified KeyedObjectPool. - * <p> - * <b>Note:</b> This should not be used on pool implementations that already - * provide proper synchronization such as the pools provided in the Commons - * Pool library. Wrapping a pool that {@link #wait() waits} for poolable - * objects to be returned before allowing another one to be borrowed with - * another layer of synchronization will cause liveliness issues or a - * deadlock. - * </p> - * - * @param keyedPool - * the KeyedObjectPool to be "wrapped" in a synchronized - * KeyedObjectPool. - * @param <K> the type of the pool key - * @param <V> the type of pool entries - * @return a synchronized view of the specified KeyedObjectPool. - */ - public static <K, V> KeyedObjectPool<K, V> synchronizedPool( - final KeyedObjectPool<K, V> keyedPool) { - /* - * assert !(keyedPool instanceof GenericKeyedObjectPool) : - * "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool - * instanceof StackKeyedObjectPool) : - * "StackKeyedObjectPool is already thread-safe"; assert - * !"org.apache.commons.pool.composite.CompositeKeyedObjectPool" - * .equals(keyedPool.getClass().getName()) : - * "CompositeKeyedObjectPools are already thread-safe"; - */ - return new SynchronizedKeyedObjectPool<>(keyedPool); + keyedPool.addObjects(keys, count); } /** @@ -396,167 +320,6 @@ public final class PoolUtils { } /** - * Returns a pool that adaptively decreases its size when idle objects are - * no longer needed. This is intended as an always thread-safe alternative - * to using an idle object evictor provided by many pool implementations. - * This is also an effective way to shrink FIFO ordered pools that - * experience load spikes. - * - * @param pool - * the ObjectPool to be decorated so it shrinks its idle count - * when possible. - * @param <T> the type of objects in the pool - * @return a pool that adaptively decreases its size when idle objects are - * no longer needed. - * @see #erodingPool(ObjectPool, float) - */ - public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool) { - return erodingPool(pool, 1f); - } - - /** - * Returns a pool that adaptively decreases its size when idle objects are - * no longer needed. This is intended as an always thread-safe alternative - * to using an idle object evictor provided by many pool implementations. - * This is also an effective way to shrink FIFO ordered pools that - * experience load spikes. - * <p> - * The factor parameter provides a mechanism to tweak the rate at which the - * pool tries to shrink its size. Values between 0 and 1 cause the pool to - * try to shrink its size more often. Values greater than 1 cause the pool - * to less frequently try to shrink its size. - * </p> - * - * @param pool - * the ObjectPool to be decorated so it shrinks its idle count - * when possible. - * @param factor - * a positive value to scale the rate at which the pool tries to - * reduce its size. If 0 < factor < 1 then the pool - * shrinks more aggressively. If 1 < factor then the pool - * shrinks less aggressively. - * @param <T> the type of objects in the pool - * @return a pool that adaptively decreases its size when idle objects are - * no longer needed. - * @see #erodingPool(ObjectPool) - */ - public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool, - final float factor) { - if (pool == null) { - throw new IllegalArgumentException(MSG_NULL_POOL); - } - if (factor <= 0f) { - throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE); - } - return new ErodingObjectPool<>(pool, factor); - } - - /** - * Returns a pool that adaptively decreases its size when idle objects are - * no longer needed. This is intended as an always thread-safe alternative - * to using an idle object evictor provided by many pool implementations. - * This is also an effective way to shrink FIFO ordered pools that - * experience load spikes. - * - * @param keyedPool - * the KeyedObjectPool to be decorated so it shrinks its idle - * count when possible. - * @param <K> the type of the pool key - * @param <V> the type of pool entries - * @return a pool that adaptively decreases its size when idle objects are - * no longer needed. - * @see #erodingPool(KeyedObjectPool, float) - * @see #erodingPool(KeyedObjectPool, float, boolean) - */ - public static <K, V> KeyedObjectPool<K, V> erodingPool( - final KeyedObjectPool<K, V> keyedPool) { - return erodingPool(keyedPool, 1f); - } - - /** - * Returns a pool that adaptively decreases its size when idle objects are - * no longer needed. This is intended as an always thread-safe alternative - * to using an idle object evictor provided by many pool implementations. - * This is also an effective way to shrink FIFO ordered pools that - * experience load spikes. - * <p> - * The factor parameter provides a mechanism to tweak the rate at which the - * pool tries to shrink its size. Values between 0 and 1 cause the pool to - * try to shrink its size more often. Values greater than 1 cause the pool - * to less frequently try to shrink its size. - * </p> - * - * @param keyedPool - * the KeyedObjectPool to be decorated so it shrinks its idle - * count when possible. - * @param factor - * a positive value to scale the rate at which the pool tries to - * reduce its size. If 0 < factor < 1 then the pool - * shrinks more aggressively. If 1 < factor then the pool - * shrinks less aggressively. - * @param <K> the type of the pool key - * @param <V> the type of pool entries - * @return a pool that adaptively decreases its size when idle objects are - * no longer needed. - * @see #erodingPool(KeyedObjectPool, float, boolean) - */ - public static <K, V> KeyedObjectPool<K, V> erodingPool( - final KeyedObjectPool<K, V> keyedPool, final float factor) { - return erodingPool(keyedPool, factor, false); - } - - /** - * Returns a pool that adaptively decreases its size when idle objects are - * no longer needed. This is intended as an always thread-safe alternative - * to using an idle object evictor provided by many pool implementations. - * This is also an effective way to shrink FIFO ordered pools that - * experience load spikes. - * <p> - * The factor parameter provides a mechanism to tweak the rate at which the - * pool tries to shrink its size. Values between 0 and 1 cause the pool to - * try to shrink its size more often. Values greater than 1 cause the pool - * to less frequently try to shrink its size. - * </p> - * <p> - * The perKey parameter determines if the pool shrinks on a whole pool basis - * or a per key basis. When perKey is false, the keys do not have an effect - * on the rate at which the pool tries to shrink its size. When perKey is - * true, each key is shrunk independently. - * </p> - * - * @param keyedPool - * the KeyedObjectPool to be decorated so it shrinks its idle - * count when possible. - * @param factor - * a positive value to scale the rate at which the pool tries to - * reduce its size. If 0 < factor < 1 then the pool - * shrinks more aggressively. If 1 < factor then the pool - * shrinks less aggressively. - * @param perKey - * when true, each key is treated independently. - * @param <K> the type of the pool key - * @param <V> the type of pool entries - * @return a pool that adaptively decreases its size when idle objects are - * no longer needed. - * @see #erodingPool(KeyedObjectPool) - * @see #erodingPool(KeyedObjectPool, float) - */ - public static <K, V> KeyedObjectPool<K, V> erodingPool( - final KeyedObjectPool<K, V> keyedPool, final float factor, - final boolean perKey) { - if (keyedPool == null) { - throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); - } - if (factor <= 0f) { - throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE); - } - if (perKey) { - return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor); - } - return new ErodingKeyedObjectPool<>(keyedPool, factor); - } - - /** * Gets the <code>Timer</code> for checking keyedPool's idle count. * * @return the {@link Timer} for checking keyedPool's idle count. @@ -718,73 +481,51 @@ public final class PoolUtils { } /** - * A synchronized (thread-safe) ObjectPool backed by the specified - * ObjectPool. + * A fully synchronized PooledObjectFactory that wraps a + * PooledObjectFactory and synchronizes access to the wrapped factory + * methods. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons - * Pool library. Wrapping a pool that {@link #wait() waits} for poolable - * objects to be returned before allowing another one to be borrowed with - * another layer of synchronization will cause liveliness issues or a - * deadlock. + * Pool library. * </p> * - * @param <T> type of objects in the pool + * @param <T> pooled object factory type */ - private static final class SynchronizedObjectPool<T> implements ObjectPool<T> { + private static final class SynchronizedPooledObjectFactory<T> implements + PooledObjectFactory<T> { - /** - * Object whose monitor is used to synchronize methods on the wrapped - * pool. - */ - private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + /** Synchronization lock */ + private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); - /** the underlying object pool */ - private final ObjectPool<T> pool; + /** Wrapped factory */ + private final PooledObjectFactory<T> factory; /** - * Creates a new SynchronizedObjectPool wrapping the given pool. + * Creates a SynchronizedPoolableObjectFactory wrapping the given + * factory. * - * @param pool - * the ObjectPool to be "wrapped" in a synchronized - * ObjectPool. + * @param factory + * underlying factory to wrap * @throws IllegalArgumentException - * if the pool is null + * if the factory is null */ - SynchronizedObjectPool(final ObjectPool<T> pool) + SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory) throws IllegalArgumentException { - if (pool == null) { - throw new IllegalArgumentException(MSG_NULL_POOL); - } - this.pool = pool; - } - - /** - * {@inheritDoc} - */ - @Override - public T borrowObject() throws Exception, NoSuchElementException, - IllegalStateException { - final WriteLock writeLock = readWriteLock.writeLock(); - writeLock.lock(); - try { - return pool.borrowObject(); - } finally { - writeLock.unlock(); + if (factory == null) { + throw new IllegalArgumentException("factory must not be null."); } + this.factory = factory; } /** * {@inheritDoc} */ @Override - public void returnObject(final T obj) { - final WriteLock writeLock = readWriteLock.writeLock(); + public PooledObject<T> makeObject() throws Exception { writeLock.lock(); try { - pool.returnObject(obj); - } catch (final Exception e) { - // swallowed as of Pool 2 + return factory.makeObject(); } finally { writeLock.unlock(); } @@ -794,13 +535,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void invalidateObject(final T obj) { - final WriteLock writeLock = readWriteLock.writeLock(); + public void destroyObject(final PooledObject<T> p) throws Exception { writeLock.lock(); try { - pool.invalidateObject(obj); - } catch (final Exception e) { - // swallowed as of Pool 2 + factory.destroyObject(p); } finally { writeLock.unlock(); } @@ -810,12 +548,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void addObject() throws Exception, IllegalStateException, - UnsupportedOperationException { - final WriteLock writeLock = readWriteLock.writeLock(); + public boolean validateObject(final PooledObject<T> p) { writeLock.lock(); try { - pool.addObject(); + return factory.validateObject(p); } finally { writeLock.unlock(); } @@ -825,39 +561,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public int getNumIdle() { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return pool.getNumIdle(); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive() { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return pool.getNumActive(); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void clear() throws Exception, UnsupportedOperationException { - final WriteLock writeLock = readWriteLock.writeLock(); + public void activateObject(final PooledObject<T> p) throws Exception { writeLock.lock(); try { - pool.clear(); + factory.activateObject(p); } finally { writeLock.unlock(); } @@ -867,13 +574,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void close() { - final WriteLock writeLock = readWriteLock.writeLock(); + public void passivateObject(final PooledObject<T> p) throws Exception { writeLock.lock(); try { - pool.close(); - } catch (final Exception e) { - // swallowed as of Pool 2 + factory.passivateObject(p); } finally { writeLock.unlock(); } @@ -885,83 +589,62 @@ public final class PoolUtils { @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("SynchronizedObjectPool"); - sb.append("{pool=").append(pool); + sb.append("SynchronizedPoolableObjectFactory"); + sb.append("{factory=").append(factory); sb.append('}'); return sb.toString(); } } /** - * A synchronized (thread-safe) KeyedObjectPool backed by the specified - * KeyedObjectPool. + * A fully synchronized KeyedPooledObjectFactory that wraps a + * KeyedPooledObjectFactory and synchronizes access to the wrapped factory + * methods. * <p> * <b>Note:</b> This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons - * Pool library. Wrapping a pool that {@link #wait() waits} for poolable - * objects to be returned before allowing another one to be borrowed with - * another layer of synchronization will cause liveliness issues or a - * deadlock. + * Pool library. * </p> * - * @param <K> object pool key type - * @param <V> object pool value type + * @param <K> pooled object factory key type + * @param <V> pooled object factory key value */ - private static final class SynchronizedKeyedObjectPool<K, V> implements - KeyedObjectPool<K, V> { + private static final class SynchronizedKeyedPooledObjectFactory<K, V> + implements KeyedPooledObjectFactory<K, V> { - /** - * Object whose monitor is used to synchronize methods on the wrapped - * pool. - */ - private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + /** Synchronization lock */ + private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); - /** Underlying object pool */ - private final KeyedObjectPool<K, V> keyedPool; + /** Wrapped factory */ + private final KeyedPooledObjectFactory<K, V> keyedFactory; /** - * Creates a new SynchronizedKeyedObjectPool wrapping the given pool + * Creates a SynchronizedKeyedPoolableObjectFactory wrapping the given + * factory. * - * @param keyedPool - * KeyedObjectPool to wrap + * @param keyedFactory + * underlying factory to wrap * @throws IllegalArgumentException - * if keyedPool is null + * if the factory is null */ - SynchronizedKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool) + SynchronizedKeyedPooledObjectFactory( + final KeyedPooledObjectFactory<K, V> keyedFactory) throws IllegalArgumentException { - if (keyedPool == null) { + if (keyedFactory == null) { throw new IllegalArgumentException( - MSG_NULL_KEYED_POOL); - } - this.keyedPool = keyedPool; - } - - /** - * {@inheritDoc} - */ - @Override - public V borrowObject(final K key) throws Exception, - NoSuchElementException, IllegalStateException { - final WriteLock writeLock = readWriteLock.writeLock(); - writeLock.lock(); - try { - return keyedPool.borrowObject(key); - } finally { - writeLock.unlock(); + "keyedFactory must not be null."); } + this.keyedFactory = keyedFactory; } /** * {@inheritDoc} */ @Override - public void returnObject(final K key, final V obj) { - final WriteLock writeLock = readWriteLock.writeLock(); + public PooledObject<V> makeObject(final K key) throws Exception { writeLock.lock(); try { - keyedPool.returnObject(key, obj); - } catch (final Exception e) { - // swallowed + return keyedFactory.makeObject(key); } finally { writeLock.unlock(); } @@ -971,13 +654,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void invalidateObject(final K key, final V obj) { - final WriteLock writeLock = readWriteLock.writeLock(); + public void destroyObject(final K key, final PooledObject<V> p) throws Exception { writeLock.lock(); try { - keyedPool.invalidateObject(key, obj); - } catch (final Exception e) { - // swallowed as of Pool 2 + keyedFactory.destroyObject(key, p); } finally { writeLock.unlock(); } @@ -987,12 +667,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void addObject(final K key) throws Exception, - IllegalStateException, UnsupportedOperationException { - final WriteLock writeLock = readWriteLock.writeLock(); + public boolean validateObject(final K key, final PooledObject<V> p) { writeLock.lock(); try { - keyedPool.addObject(key); + return keyedFactory.validateObject(key, p); } finally { writeLock.unlock(); } @@ -1002,67 +680,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public int getNumIdle(final K key) { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return keyedPool.getNumIdle(key); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive(final K key) { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return keyedPool.getNumActive(key); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumIdle() { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return keyedPool.getNumIdle(); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive() { - final ReadLock readLock = readWriteLock.readLock(); - readLock.lock(); - try { - return keyedPool.getNumActive(); - } finally { - readLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void clear() throws Exception, UnsupportedOperationException { - final WriteLock writeLock = readWriteLock.writeLock(); + public void activateObject(final K key, final PooledObject<V> p) throws Exception { writeLock.lock(); try { - keyedPool.clear(); + keyedFactory.activateObject(key, p); } finally { writeLock.unlock(); } @@ -1072,263 +693,10 @@ public final class PoolUtils { * {@inheritDoc} */ @Override - public void clear(final K key) throws Exception, - UnsupportedOperationException { - final WriteLock writeLock = readWriteLock.writeLock(); + public void passivateObject(final K key, final PooledObject<V> p) throws Exception { writeLock.lock(); try { - keyedPool.clear(key); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void close() { - final WriteLock writeLock = readWriteLock.writeLock(); - writeLock.lock(); - try { - keyedPool.close(); - } catch (final Exception e) { - // swallowed as of Pool 2 - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("SynchronizedKeyedObjectPool"); - sb.append("{keyedPool=").append(keyedPool); - sb.append('}'); - return sb.toString(); - } - } - - /** - * A fully synchronized PooledObjectFactory that wraps a - * PooledObjectFactory and synchronizes access to the wrapped factory - * methods. - * <p> - * <b>Note:</b> This should not be used on pool implementations that already - * provide proper synchronization such as the pools provided in the Commons - * Pool library. - * </p> - * - * @param <T> pooled object factory type - */ - private static final class SynchronizedPooledObjectFactory<T> implements - PooledObjectFactory<T> { - - /** Synchronization lock */ - private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); - - /** Wrapped factory */ - private final PooledObjectFactory<T> factory; - - /** - * Creates a SynchronizedPoolableObjectFactory wrapping the given - * factory. - * - * @param factory - * underlying factory to wrap - * @throws IllegalArgumentException - * if the factory is null - */ - SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory) - throws IllegalArgumentException { - if (factory == null) { - throw new IllegalArgumentException("factory must not be null."); - } - this.factory = factory; - } - - /** - * {@inheritDoc} - */ - @Override - public PooledObject<T> makeObject() throws Exception { - writeLock.lock(); - try { - return factory.makeObject(); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void destroyObject(final PooledObject<T> p) throws Exception { - writeLock.lock(); - try { - factory.destroyObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean validateObject(final PooledObject<T> p) { - writeLock.lock(); - try { - return factory.validateObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void activateObject(final PooledObject<T> p) throws Exception { - writeLock.lock(); - try { - factory.activateObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void passivateObject(final PooledObject<T> p) throws Exception { - writeLock.lock(); - try { - factory.passivateObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("SynchronizedPoolableObjectFactory"); - sb.append("{factory=").append(factory); - sb.append('}'); - return sb.toString(); - } - } - - /** - * A fully synchronized KeyedPooledObjectFactory that wraps a - * KeyedPooledObjectFactory and synchronizes access to the wrapped factory - * methods. - * <p> - * <b>Note:</b> This should not be used on pool implementations that already - * provide proper synchronization such as the pools provided in the Commons - * Pool library. - * </p> - * - * @param <K> pooled object factory key type - * @param <V> pooled object factory key value - */ - private static final class SynchronizedKeyedPooledObjectFactory<K, V> - implements KeyedPooledObjectFactory<K, V> { - - /** Synchronization lock */ - private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); - - /** Wrapped factory */ - private final KeyedPooledObjectFactory<K, V> keyedFactory; - - /** - * Creates a SynchronizedKeyedPoolableObjectFactory wrapping the given - * factory. - * - * @param keyedFactory - * underlying factory to wrap - * @throws IllegalArgumentException - * if the factory is null - */ - SynchronizedKeyedPooledObjectFactory( - final KeyedPooledObjectFactory<K, V> keyedFactory) - throws IllegalArgumentException { - if (keyedFactory == null) { - throw new IllegalArgumentException( - "keyedFactory must not be null."); - } - this.keyedFactory = keyedFactory; - } - - /** - * {@inheritDoc} - */ - @Override - public PooledObject<V> makeObject(final K key) throws Exception { - writeLock.lock(); - try { - return keyedFactory.makeObject(key); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void destroyObject(final K key, final PooledObject<V> p) throws Exception { - writeLock.lock(); - try { - keyedFactory.destroyObject(key, p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean validateObject(final K key, final PooledObject<V> p) { - writeLock.lock(); - try { - return keyedFactory.validateObject(key, p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void activateObject(final K key, final PooledObject<V> p) throws Exception { - writeLock.lock(); - try { - keyedFactory.activateObject(key, p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void passivateObject(final K key, final PooledObject<V> p) throws Exception { - writeLock.lock(); - try { - keyedFactory.passivateObject(key, p); + keyedFactory.passivateObject(key, p); } finally { writeLock.unlock(); } @@ -1346,492 +714,4 @@ public final class PoolUtils { return sb.toString(); } } - - /** - * Encapsulate the logic for when the next poolable object should be - * discarded. Each time update is called, the next time to shrink is - * recomputed, based on the float factor, number of idle instances in the - * pool and high water mark. Float factor is assumed to be between 0 and 1. - * Values closer to 1 cause less frequent erosion events. Erosion event - * timing also depends on numIdle. When this value is relatively high (close - * to previously established high water mark), erosion occurs more - * frequently. - */ - private static final class ErodingFactor { - /** Determines frequency of "erosion" events */ - private final float factor; - - /** Time of next shrink event */ - private transient volatile long nextShrink; - - /** High water mark - largest numIdle encountered */ - private transient volatile int idleHighWaterMark; - - /** - * Creates a new ErodingFactor with the given erosion factor. - * - * @param factor - * erosion factor - */ - public ErodingFactor(final float factor) { - this.factor = factor; - nextShrink = System.currentTimeMillis() + (long) (900000 * factor); // now - // + - // 15 - // min - // * - // factor - idleHighWaterMark = 1; - } - - /** - * Updates internal state using the supplied time and numIdle. - * - * @param now - * current time - * @param numIdle - * number of idle elements in the pool - */ - public void update(final long now, final int numIdle) { - final int idle = Math.max(0, numIdle); - idleHighWaterMark = Math.max(idle, idleHighWaterMark); - final float maxInterval = 15f; - final float minutes = maxInterval + - ((1f - maxInterval) / idleHighWaterMark) * idle; - nextShrink = now + (long) (minutes * 60000f * factor); - } - - /** - * Returns the time of the next erosion event. - * - * @return next shrink time - */ - public long getNextShrink() { - return nextShrink; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "ErodingFactor{" + "factor=" + factor + - ", idleHighWaterMark=" + idleHighWaterMark + '}'; - } - } - - /** - * Decorates an object pool, adding "eroding" behavior. Based on the - * configured {@link #factor erosion factor}, objects returning to the pool - * may be invalidated instead of being added to idle capacity. - * - * @param <T> type of objects in the pool - */ - private static class ErodingObjectPool<T> implements ObjectPool<T> { - - /** Underlying object pool */ - private final ObjectPool<T> pool; - - /** Erosion factor */ - private final ErodingFactor factor; - - /** - * Creates an ErodingObjectPool wrapping the given pool using the - * specified erosion factor. - * - * @param pool - * underlying pool - * @param factor - * erosion factor - determines the frequency of erosion - * events - * @see #factor - */ - public ErodingObjectPool(final ObjectPool<T> pool, final float factor) { - this.pool = pool; - this.factor = new ErodingFactor(factor); - } - - /** - * {@inheritDoc} - */ - @Override - public T borrowObject() throws Exception, NoSuchElementException, - IllegalStateException { - return pool.borrowObject(); - } - - /** - * Returns obj to the pool, unless erosion is triggered, in which case - * obj is invalidated. Erosion is triggered when there are idle - * instances in the pool and more than the {@link #factor erosion - * factor}-determined time has elapsed since the last returnObject - * activation. - * - * @param obj - * object to return or invalidate - * @see #factor - */ - @Override - public void returnObject(final T obj) { - boolean discard = false; - final long now = System.currentTimeMillis(); - synchronized (pool) { - if (factor.getNextShrink() < now) { // XXX: Pool 3: move test - // out of sync block - final int numIdle = pool.getNumIdle(); - if (numIdle > 0) { - discard = true; - } - - factor.update(now, numIdle); - } - } - try { - if (discard) { - pool.invalidateObject(obj); - } else { - pool.returnObject(obj); - } - } catch (final Exception e) { - // swallowed - } - } - - /** - * {@inheritDoc} - */ - @Override - public void invalidateObject(final T obj) { - try { - pool.invalidateObject(obj); - } catch (final Exception e) { - // swallowed - } - } - - /** - * {@inheritDoc} - */ - @Override - public void addObject() throws Exception, IllegalStateException, - UnsupportedOperationException { - pool.addObject(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumIdle() { - return pool.getNumIdle(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive() { - return pool.getNumActive(); - } - - /** - * {@inheritDoc} - */ - @Override - public void clear() throws Exception, UnsupportedOperationException { - pool.clear(); - } - - /** - * {@inheritDoc} - */ - @Override - public void close() { - try { - pool.close(); - } catch (final Exception e) { - // swallowed - } - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "ErodingObjectPool{" + "factor=" + factor + ", pool=" + - pool + '}'; - } - } - - /** - * Decorates a keyed object pool, adding "eroding" behavior. Based on the - * configured erosion factor, objects returning to the pool - * may be invalidated instead of being added to idle capacity. - * - * @param <K> object pool key type - * @param <V> object pool value type - */ - private static class ErodingKeyedObjectPool<K, V> implements - KeyedObjectPool<K, V> { - - /** Underlying pool */ - private final KeyedObjectPool<K, V> keyedPool; - - /** Erosion factor */ - private final ErodingFactor erodingFactor; - - /** - * Creates an ErodingObjectPool wrapping the given pool using the - * specified erosion factor. - * - * @param keyedPool - * underlying pool - * @param factor - * erosion factor - determines the frequency of erosion - * events - * @see #erodingFactor - */ - public ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, - final float factor) { - this(keyedPool, new ErodingFactor(factor)); - } - - /** - * Creates an ErodingObjectPool wrapping the given pool using the - * specified erosion factor. - * - * @param keyedPool - * underlying pool - must not be null - * @param erodingFactor - * erosion factor - determines the frequency of erosion - * events - * @see #erodingFactor - */ - protected ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, - final ErodingFactor erodingFactor) { - if (keyedPool == null) { - throw new IllegalArgumentException( - MSG_NULL_KEYED_POOL); - } - this.keyedPool = keyedPool; - this.erodingFactor = erodingFactor; - } - - /** - * {@inheritDoc} - */ - @Override - public V borrowObject(final K key) throws Exception, - NoSuchElementException, IllegalStateException { - return keyedPool.borrowObject(key); - } - - /** - * Returns obj to the pool, unless erosion is triggered, in which case - * obj is invalidated. Erosion is triggered when there are idle - * instances in the pool associated with the given key and more than the - * configured {@link #erodingFactor erosion factor} time has elapsed - * since the last returnObject activation. - * - * @param obj - * object to return or invalidate - * @param key - * key - * @see #erodingFactor - */ - @Override - public void returnObject(final K key, final V obj) throws Exception { - boolean discard = false; - final long now = System.currentTimeMillis(); - final ErodingFactor factor = getErodingFactor(key); - synchronized (keyedPool) { - if (factor.getNextShrink() < now) { - final int numIdle = getNumIdle(key); - if (numIdle > 0) { - discard = true; - } - - factor.update(now, numIdle); - } - } - try { - if (discard) { - keyedPool.invalidateObject(key, obj); - } else { - keyedPool.returnObject(key, obj); - } - } catch (final Exception e) { - // swallowed - } - } - - /** - * Returns the eroding factor for the given key - * - * @param key - * key - * @return eroding factor for the given keyed pool - */ - protected ErodingFactor getErodingFactor(final K key) { - return erodingFactor; - } - - /** - * {@inheritDoc} - */ - @Override - public void invalidateObject(final K key, final V obj) { - try { - keyedPool.invalidateObject(key, obj); - } catch (final Exception e) { - // swallowed - } - } - - /** - * {@inheritDoc} - */ - @Override - public void addObject(final K key) throws Exception, - IllegalStateException, UnsupportedOperationException { - keyedPool.addObject(key); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumIdle() { - return keyedPool.getNumIdle(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumIdle(final K key) { - return keyedPool.getNumIdle(key); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive() { - return keyedPool.getNumActive(); - } - - /** - * {@inheritDoc} - */ - @Override - public int getNumActive(final K key) { - return keyedPool.getNumActive(key); - } - - /** - * {@inheritDoc} - */ - @Override - public void clear() throws Exception, UnsupportedOperationException { - keyedPool.clear(); - } - - /** - * {@inheritDoc} - */ - @Override - public void clear(final K key) throws Exception, - UnsupportedOperationException { - keyedPool.clear(key); - } - - /** - * {@inheritDoc} - */ - @Override - public void close() { - try { - keyedPool.close(); - } catch (final Exception e) { - // swallowed - } - } - - /** - * Returns the underlying pool - * - * @return the keyed pool that this ErodingKeyedObjectPool wraps - */ - protected KeyedObjectPool<K, V> getKeyedPool() { - return keyedPool; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "ErodingKeyedObjectPool{" + "factor=" + - erodingFactor + ", keyedPool=" + keyedPool + '}'; - } - } - - /** - * Extends ErodingKeyedObjectPool to allow erosion to take place on a - * per-key basis. Timing of erosion events is tracked separately for - * separate keyed pools. - * - * @param <K> object pool key type - * @param <V> object pool value type - */ - private static final class ErodingPerKeyKeyedObjectPool<K, V> extends - ErodingKeyedObjectPool<K, V> { - - /** Erosion factor - same for all pools */ - private final float factor; - - /** Map of ErodingFactor instances keyed on pool keys */ - private final Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<K, ErodingFactor>()); - - /** - * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed - * pool with the specified erosion factor. - * - * @param keyedPool - * underlying keyed pool - * @param factor - * erosion factor - */ - public ErodingPerKeyKeyedObjectPool( - final KeyedObjectPool<K, V> keyedPool, final float factor) { - super(keyedPool, null); - this.factor = factor; - } - - /** - * {@inheritDoc} - */ - @Override - protected ErodingFactor getErodingFactor(final K key) { - ErodingFactor eFactor = factors.get(key); - // this may result in two ErodingFactors being created for a key - // since they are small and cheap this is okay. - if (eFactor == null) { - eFactor = new ErodingFactor(this.factor); - factors.put(key, eFactor); - } - return eFactor; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + - ", keyedPool=" + getKeyedPool() + '}'; - } - } } diff --git a/java/org/apache/tomcat/dbcp/pool2/PooledObject.java b/java/org/apache/tomcat/dbcp/pool2/PooledObject.java index 361b3d8..1bfb803 100644 --- a/java/org/apache/tomcat/dbcp/pool2/PooledObject.java +++ b/java/org/apache/tomcat/dbcp/pool2/PooledObject.java @@ -24,6 +24,7 @@ import java.util.Deque; * state, for the pooled objects. * <p> * Implementations of this class are required to be thread-safe. + * </p> * * @param <T> the type of object in the pool * @@ -185,7 +186,7 @@ public interface PooledObject<T> extends Comparable<PooledObject<T>> { * @param requireFullStackTrace the new configuration setting for abandoned object logging * @since 2.7.0 */ - void setRequireFullStackTrace(boolean requireFullStackTrace); + void setRequireFullStackTrace(final boolean requireFullStackTrace); /** * Record the current stack trace as the last time the object was used. diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java b/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java index fdacc6e..fc618a5 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java @@ -31,7 +31,9 @@ import org.apache.tomcat.dbcp.pool2.PooledObject; * {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} / * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleTimeMillis()} * </ul> + * <p> * This class is immutable and thread-safe. + * </p> * * @param <T> the type of objects in the pool * diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java index 49766f0..b124676 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java @@ -22,6 +22,7 @@ package org.apache.tomcat.dbcp.pool2.impl; * its own specific configuration attributes. * <p> * This class is immutable and thread-safe. + * </p> * * @since 2.0 */ diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java index 01dc542..93c7a84 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java @@ -17,6 +17,7 @@ package org.apache.tomcat.dbcp.pool2.impl; import java.util.ArrayList; +import java.util.Collection; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; @@ -50,10 +51,12 @@ import org.apache.tomcat.dbcp.pool2.PooledObjectState; * {@link #borrowObject borrowObject} methods. Each time a new key value is * provided to one of these methods, a sub-new pool is created under the given * key to be managed by the containing <code>GenericKeyedObjectPool.</code> + * </p> * <p> * Note that the current implementation uses a ConcurrentHashMap which uses * equals() to compare keys. * This means that distinct instance keys must be distinguishable using equals. + * </p> * <p> * Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle @@ -62,12 +65,15 @@ import org.apache.tomcat.dbcp.pool2.PooledObjectState; * configuring this optional feature. Eviction runs contend with client threads * for access to objects in the pool, so if they run too frequently performance * issues may result. + * </p> * <p> * Implementation note: To prevent possible deadlocks, care has been taken to * ensure that no call to a factory method will occur within a synchronization * block. See POOL-125 and DBCP-44 for more information. + * </p> * <p> * This class is intended to be thread-safe. + * </p> * * @see GenericObjectPool * @@ -447,6 +453,11 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> final ObjectDeque<T> objectDeque = poolMap.get(key); + if (objectDeque == null) { + throw new IllegalStateException( + "No keyed pool found under the given key."); + } + final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj)); if (p == null) { @@ -1077,8 +1088,16 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> final ObjectDeque<T> objectDeque = register(key); try { - final boolean isIdle = objectDeque.getIdleObjects().remove(toDestroy); - + boolean isIdle; + synchronized(toDestroy) { + // Check idle state directly + isIdle = toDestroy.getState().equals(PooledObjectState.IDLE); + // If idle, not under eviction test, or always is true, remove instance, + // updating isIdle if instance is found in idle objects + if (isIdle || always) { + isIdle = objectDeque.getIdleObjects().remove(toDestroy); + } + } if (isIdle || always) { objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject())); toDestroy.invalidate(); @@ -1151,10 +1170,9 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> */ private void deregister(final K k) { Lock lock = keyLock.readLock(); - ObjectDeque<T> objectDeque; try { lock.lock(); - objectDeque = poolMap.get(k); + final ObjectDeque<T> objectDeque = poolMap.get(k); final long numInterested = objectDeque.getNumInterested().decrementAndGet(); if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) { // Potential to remove key @@ -1244,6 +1262,58 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> } /** + * Calls {@link KeyedObjectPool#addObject(Object)} with each + * key in <code>keys</code> for <code>count</code> number of times. This has + * the same effect as calling {@link #addObjects(Object, int)} + * for each key in the <code>keys</code> collection. + * + * @param keys + * {@link Collection} of keys to add objects for. + * @param count + * the number of idle objects to add for each <code>key</code>. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when <code>keyedPool</code>, <code>keys</code>, or any value + * in <code>keys</code> is <code>null</code>. + * @see #addObjects(Object, int) + */ + @Override + public void addObjects(final Collection<K> keys, final int count) throws Exception, IllegalArgumentException { + if (keys == null) { + throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEYS); + } + final Iterator<K> iter = keys.iterator(); + while (iter.hasNext()) { + addObjects(iter.next(), count); + } + } + + /** + * Calls {@link KeyedObjectPool#addObject(Object)} + * <code>key</code> <code>count</code> number of times. + * + * @param key + * the key to add objects for. + * @param count + * the number of idle objects to add for <code>key</code>. + * @throws Exception + * when {@link KeyedObjectPool#addObject(Object)} fails. + * @throws IllegalArgumentException + * when <code>key</code> is <code>null</code>. + * @since 2.8.0 + */ + @Override + public void addObjects(final K key, final int count) throws Exception, IllegalArgumentException { + if (key == null) { + throw new IllegalArgumentException(PoolUtils.MSG_NULL_KEY); + } + for (int i = 0; i < count; i++) { + addObject(key); + } + } + + /** * Add an object to the set of idle objects for a given key. * * @param key The key to associate with the idle object diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java index c72b701..4a9909d 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java @@ -38,7 +38,8 @@ import org.apache.tomcat.dbcp.pool2.UsageTracking; * <p> * When coupled with the appropriate {@link PooledObjectFactory}, * <code>GenericObjectPool</code> provides robust pooling functionality for - * arbitrary objects.</p> + * arbitrary objects. + * </p> * <p> * Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle @@ -46,7 +47,8 @@ import org.apache.tomcat.dbcp.pool2.UsageTracking; * which runs asynchronously. Caution should be used when configuring this * optional feature. Eviction runs contend with client threads for access to * objects in the pool, so if they run too frequently performance issues may - * result.</p> + * result. + * </p> * <p> * The pool can also be configured to detect and remove "abandoned" objects, * i.e. objects that have been checked out of the pool but neither used nor @@ -59,13 +61,16 @@ import org.apache.tomcat.dbcp.pool2.UsageTracking; * their last use will be queried * using the <code>getLastUsed</code> method on that interface; otherwise * abandonment is determined by how long an object has been checked out from - * the pool.</p> + * the pool. + * </p> * <p> * Implementation note: To prevent possible deadlocks, care has been taken to * ensure that no call to a factory method will occur within a synchronization - * block. See POOL-125 and DBCP-44 for more information.</p> + * block. See POOL-125 and DBCP-44 for more information. + * </p> * <p> - * This class is intended to be thread-safe.</p> + * This class is intended to be thread-safe. + * </p> * * @see GenericKeyedObjectPool * @@ -576,6 +581,11 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } catch (final Exception e) { swallowException(e); } + try { + ensureIdle(1, false); + } catch (final Exception e) { + swallowException(e); + } } else { if (getLifo()) { idleObjects.addFirst(p); @@ -931,15 +941,6 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> destroyedCount.incrementAndGet(); createCount.decrementAndGet(); } - - if (idleObjects.isEmpty() && idleObjects.hasTakeWaiters()) { - // POOL-356. - // In case there are already threads waiting on something in the pool - // (e.g. idleObjects.takeFirst(); then we need to provide them a fresh instance. - // Otherwise they will be stuck forever (or until timeout) - final PooledObject<T> freshPooled = create(); - idleObjects.put(freshPooled); - } } @Override @@ -1005,6 +1006,23 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } /** + * Calls {@link ObjectPool#addObject()} <code>count</code> + * number of times. + * + * @param count + * the number of idle objects to add. + * @throws Exception + * when {@link ObjectPool#addObject()} fails. + * @since 2.8.0 + */ + @Override + public void addObjects(final int count) throws Exception { + for (int i = 0; i < count; i++) { + addObject(); + } + } + + /** * Adds the provided wrapped pooled object to the set of idle objects for * this pool. The object must already be part of the pool. If {@code p} * is null, this is a no-op (no exception, but no impact on the pool). diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java b/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java index 5a51b92..b539aed 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java @@ -26,6 +26,7 @@ import java.util.concurrent.locks.ReentrantLock; * class is intended for internal use only. * <p> * This class is intended to be thread-safe. + * </p> * * @since 2.0 */ diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java b/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java index be92f91..75e925e 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java @@ -34,6 +34,7 @@ import java.util.concurrent.locks.Condition; * is equal to {@link Integer#MAX_VALUE}. Linked nodes are * dynamically created upon each insertion unless this would bring the * deque above capacity. + * </p> * * <p>Most operations run in constant time (ignoring time spent * blocking). Exceptions include {@link #remove(Object) remove}, @@ -41,14 +42,17 @@ import java.util.concurrent.locks.Condition; * #removeLastOccurrence removeLastOccurrence}, {@link #contains * contains}, {@link #iterator iterator.remove()}, and the bulk * operations, all of which run in linear time. + * </p> * * <p>This class and its iterator implement all of the * <em>optional</em> methods of the {@link Collection} and {@link * Iterator} interfaces. + * </p> * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. + * </p> * * @param <E> the type of elements held in this collection * diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java index 61741be..e417b48 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java @@ -32,6 +32,7 @@ import org.apache.tomcat.dbcp.pool2.PooledObjectFactory; * {@link org.apache.tomcat.dbcp.pool2.ObjectPool}. * <p> * This class is intended to be thread-safe. + * </p> * * @param <T> * Type of element pooled in this pool. @@ -185,6 +186,8 @@ public class SoftReferenceObjectPool<T> extends BaseObjectPool<T> { * * @param obj * instance to return to the pool + * @throws IllegalArgumentException + * if obj is not currently part of this pool */ @Override public synchronized void returnObject(final T obj) throws Exception { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 9b8c487..86adeab 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -213,6 +213,10 @@ Update the internal fork of Apache Commons FileUpload to 2317552 (2019-12-06, 2.0-SNAPSHOT). Refactoring. (markt) </add> + <add> + Update the internal fork of Apache Commons Pool 2 to 6092f92 (2019-12-06, + 2.8.0-SNAPSHOT). Clean-up and minor refactoring. (markt) + </add> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org