This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit eeb261df715aaad54eed6dc31630ed3f7697fc8c Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri Jan 15 15:18:03 2021 +0000 Update Commons Pool 2 to 2.9.1-SNAPSHOT --- MERGE.txt | 2 +- java/org/apache/tomcat/dbcp/pool2/DestroyMode.java | 30 +++++++++++ .../apache/tomcat/dbcp/pool2/KeyedObjectPool.java | 27 ++++++++++ .../dbcp/pool2/KeyedPooledObjectFactory.java | 20 +++++++ java/org/apache/tomcat/dbcp/pool2/ObjectPool.java | 24 +++++++++ .../tomcat/dbcp/pool2/PooledObjectFactory.java | 23 +++++++- .../tomcat/dbcp/pool2/impl/EvictionTimer.java | 2 +- .../dbcp/pool2/impl/GenericKeyedObjectPool.java | 52 +++++++++++++----- .../tomcat/dbcp/pool2/impl/GenericObjectPool.java | 63 ++++++++++++++-------- webapps/docs/changelog.xml | 4 ++ 10 files changed, 208 insertions(+), 39 deletions(-) diff --git a/MERGE.txt b/MERGE.txt index 8071016..52851d9 100644 --- a/MERGE.txt +++ b/MERGE.txt @@ -62,7 +62,7 @@ Pool2 Sub-tree src/main/java/org/apache/commons/pool2 The SHA1 ID / tag for the most recent commit to be merged to Tomcat is: -rel/commons-pool-2.8.1 +a38c52529beb04bf0815b7d95fb4a393ea110dee DBCP2 Sub-tree diff --git a/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java b/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java new file mode 100644 index 0000000..ed8ca47 --- /dev/null +++ b/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.dbcp.pool2; + +/** + * Destroy context provided to object factories via destroyObject methods. Values provide information about why the pool + * is asking for a pooled object to be destroyed. + * + * @since 2.9.0 + */ +public enum DestroyMode { + /** Normal destroy */ + NORMAL, + /** Destroy abandoned object */ + ABANDONED +} diff --git a/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java index 9e5d550..f2712d9 100644 --- a/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java @@ -269,6 +269,33 @@ public interface KeyedObjectPool<K, V> extends Closeable { */ void invalidateObject(K key, V obj) throws Exception; + + /** + * Invalidates an object from the pool, using the provided + * {@link DestroyMode}. + * <p> + * By contract, {@code obj} <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} that is + * equivalent to the one used to borrow the {@code Object} 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> + * + * @param key the key used to obtain the object + * @param obj a {@link #borrowObject borrowed} instance to be returned. + * @param mode destroy activation context provided to the factory + * + * @throws Exception if the instance cannot be invalidated + * @since 2.9.0 + */ + default void invalidateObject(final K key, final V obj, final DestroyMode mode) throws Exception { + invalidateObject(key, obj); + } + /** * Return an instance to the pool. By contract, {@code obj} * <strong>must</strong> have been obtained using diff --git a/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java b/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java index 5bf8b11..0a24a47 100644 --- a/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java +++ b/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java @@ -114,6 +114,26 @@ public interface KeyedPooledObjectFactory<K, V> { void destroyObject(K key, PooledObject<V> p) throws Exception; /** + * Destroy an instance no longer needed by the pool, using the provided {@link DestroyMode}. + * + * @param key the key used when selecting the instance + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @param mode DestroyMode providing context to the factory + * + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see KeyedObjectPool#invalidateObject + * @see #destroyObject(Object, PooledObject) + * @see DestroyMode + * @since 2.9.0 + */ + default void destroyObject(final K key, final PooledObject<V> p, final DestroyMode mode) throws Exception { + destroyObject(key, p); + } + + /** * Ensures that the instance is safe to be returned by the pool. * * @param key the key used when selecting the object diff --git a/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java index d371317..426bc96 100644 --- a/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java @@ -185,6 +185,29 @@ public interface ObjectPool<T> extends Closeable { void invalidateObject(T obj) throws Exception; /** + * Invalidates an object from the pool, using the provided + * {@link DestroyMode} + * <p> + * By contract, {@code obj} <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> + * + * @param obj a {@link #borrowObject borrowed} instance to be disposed. + * @param mode destroy activation context provided to the factory + * + * @throws Exception if the instance cannot be invalidated + * @since 2.9.0 + */ + default void invalidateObject(final T obj, final DestroyMode mode) throws Exception { + invalidateObject(obj); + } + + /** * Returns an instance to the pool. By contract, {@code obj} * <strong>must</strong> have been obtained using {@link #borrowObject()} or * a related method as defined in an implementation or sub-interface. @@ -201,4 +224,5 @@ public interface ObjectPool<T> extends Closeable { * @throws Exception if an instance cannot be returned to the pool */ void returnObject(T obj) throws Exception; + } diff --git a/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java b/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java index 4973a1c..9c95d0d 100644 --- a/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java +++ b/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java @@ -84,7 +84,8 @@ public interface PooledObjectFactory<T> { PooledObject<T> makeObject() throws Exception; /** - * Destroys an instance no longer needed by the pool. + * Destroys an instance no longer needed by the pool, using the default (NORMAL) + * DestroyMode. * <p> * It is important for implementations of this method to be aware that there * is no guarantee about what state {@code obj} will be in and the @@ -106,6 +107,26 @@ public interface PooledObjectFactory<T> { void destroyObject(PooledObject<T> p) throws Exception; /** + * Destroys an instance no longer needed by the pool, using the provided + * DestroyMode. + * + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @param mode DestroyMode providing context to the factory + * + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see ObjectPool#invalidateObject + * @see #destroyObject(PooledObject) + * @see DestroyMode + * @since 2.9.0 + */ + default void destroyObject(final PooledObject<T> p, final DestroyMode mode) throws Exception { + destroyObject(p); + } + + /** * Ensures that the instance is safe to be returned by the pool. * * @param p a {@code PooledObject} wrapping the instance to be validated diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java index 31e93d9..0e5759c 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java @@ -203,7 +203,7 @@ class EvictionTimer { * * @param ref the reference to track. */ - private WeakRunner(WeakReference<Runnable> ref) { + private WeakRunner(final WeakReference<Runnable> ref) { this.ref = ref; } diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java index 44f9c56..ebe4027 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java @@ -33,6 +33,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.apache.tomcat.dbcp.pool2.DestroyMode; import org.apache.tomcat.dbcp.pool2.KeyedObjectPool; import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory; import org.apache.tomcat.dbcp.pool2.PoolUtils; @@ -375,7 +376,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> factory.activateObject(key, p); } catch (final Exception e) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e1) { // Ignore - activation failure is more important } @@ -398,7 +399,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> } if (!validate) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); destroyedByBorrowValidationCount.incrementAndGet(); } catch (final Exception e) { // Ignore - validation failure is more important @@ -471,7 +472,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> try { if (getTestOnReturn() && !factory.validateObject(key, p)) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -484,7 +485,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> } catch (final Exception e1) { swallowException(e1); try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -503,7 +504,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -559,6 +560,27 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> */ @Override public void invalidateObject(final K key, final T obj) throws Exception { + invalidateObject(key, obj, DestroyMode.NORMAL); + } + + /** + * {@inheritDoc} + * <p> + * Activation of this method decrements the active count associated with + * the given keyed pool and attempts to destroy {@code obj.} + * + * @param key pool key + * @param obj instance to invalidate + * @param mode DestroyMode context provided to factory + * + * @throws Exception if an exception occurs destroying the + * object + * @throws IllegalStateException if obj does not belong to the pool + * under the given key + * @since 2.9.0 + */ + @Override + public void invalidateObject(final K key, final T obj, final DestroyMode mode) throws Exception { final ObjectDeque<T> objectDeque = poolMap.get(key); @@ -569,7 +591,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> } synchronized (p) { if (p.getState() != PooledObjectState.INVALID) { - destroy(key, p, true); + destroy(key, p, true, mode); } } if (objectDeque.idleObjects.hasTakeWaiters()) { @@ -627,7 +649,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> while (p != null) { try { - destroy(key, p, true); + destroy(key, p, true, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -759,7 +781,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> // Assume the destruction succeeds boolean destroyed = true; try { - destroyed = destroy(key, p, false); + destroyed = destroy(key, p, false, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -936,7 +958,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> } if (evict) { - destroy(evictionKey, underTest, true); + destroy(evictionKey, underTest, true, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } else { if (testWhileIdle) { @@ -945,18 +967,18 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> factory.activateObject(evictionKey, underTest); active = true; } catch (final Exception e) { - destroy(evictionKey, underTest, true); + destroy(evictionKey, underTest, true, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } if (active) { if (!factory.validateObject(evictionKey, underTest)) { - destroy(evictionKey, underTest, true); + destroy(evictionKey, underTest, true, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } else { try { factory.passivateObject(evictionKey, underTest); } catch (final Exception e) { - destroy(evictionKey, underTest, true); + destroy(evictionKey, underTest, true, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } } @@ -1076,10 +1098,12 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> * @param toDestroy The wrapped object to be destroyed * @param always Should the object be destroyed even if it is not currently * in the set of idle objects for the given key + * @param mode DestroyMode context provided to the factory + * * @return {@code true} if the object was destroyed, otherwise {@code false} * @throws Exception If the object destruction failed */ - private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always) + private boolean destroy(final K key, final PooledObject<T> toDestroy, final boolean always, final DestroyMode mode) throws Exception { final ObjectDeque<T> objectDeque = register(key); @@ -1100,7 +1124,7 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T> toDestroy.invalidate(); try { - factory.destroyObject(key, toDestroy); + factory.destroyObject(key, toDestroy, mode); } finally { objectDeque.getCreateCount().decrementAndGet(); destroyedCount.incrementAndGet(); diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java index 81e66ee..b2bca4f 100644 --- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java +++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java @@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import org.apache.tomcat.dbcp.pool2.DestroyMode; import org.apache.tomcat.dbcp.pool2.ObjectPool; import org.apache.tomcat.dbcp.pool2.PoolUtils; import org.apache.tomcat.dbcp.pool2.PooledObject; @@ -456,7 +457,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> factory.activateObject(p); } catch (final Exception e) { try { - destroy(p); + destroy(p, DestroyMode.NORMAL); } catch (final Exception e1) { // Ignore - activation failure is more important } @@ -479,7 +480,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } if (!validate) { try { - destroy(p); + destroy(p, DestroyMode.NORMAL); destroyedByBorrowValidationCount.incrementAndGet(); } catch (final Exception e) { // Ignore - validation failure is more important @@ -537,7 +538,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> if (getTestOnReturn() && !factory.validateObject(p)) { try { - destroy(p); + destroy(p, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -555,7 +556,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } catch (final Exception e1) { swallowException(e1); try { - destroy(p); + destroy(p, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -576,7 +577,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> final int maxIdleSave = getMaxIdle(); if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { try { - destroy(p); + destroy(p, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -605,7 +606,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> * {@inheritDoc} * <p> * Activation of this method decrements the active count and attempts to - * destroy the instance. + * destroy the instance, using the default (NORMAL) {@link DestroyMode}. * </p> * * @throws Exception if an exception occurs destroying the @@ -614,6 +615,23 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> */ @Override public void invalidateObject(final T obj) throws Exception { + invalidateObject(obj, DestroyMode.NORMAL); + } + + /** + * {@inheritDoc} + * <p> + * Activation of this method decrements the active count and attempts to + * destroy the instance, using the provided {@link DestroyMode}. + * </p> + * + * @throws Exception if an exception occurs destroying the + * object + * @throws IllegalStateException if obj does not belong to this pool + * @since 2.9.0 + */ + @Override + public void invalidateObject(final T obj, final DestroyMode mode) throws Exception { final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj)); if (p == null) { if (isAbandonedConfig()) { @@ -624,7 +642,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } synchronized (p) { if (p.getState() != PooledObjectState.INVALID) { - destroy(p); + destroy(p, mode); } } ensureIdle(1, false); @@ -655,7 +673,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> while (p != null) { try { - destroy(p); + destroy(p, DestroyMode.NORMAL); } catch (final Exception e) { swallowException(e); } @@ -775,7 +793,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> } if (evict) { - destroy(underTest); + destroy(underTest, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } else { if (testWhileIdle) { @@ -784,18 +802,18 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> factory.activateObject(underTest); active = true; } catch (final Exception e) { - destroy(underTest); + destroy(underTest, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } if (active) { if (!factory.validateObject(underTest)) { - destroy(underTest); + destroy(underTest, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } else { try { factory.passivateObject(underTest); } catch (final Exception e) { - destroy(underTest); + destroy(underTest, DestroyMode.NORMAL); destroyedByEvictorCount.incrementAndGet(); } } @@ -926,16 +944,17 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> * Destroys a wrapped pooled object. * * @param toDestroy The wrapped pooled object to destroy + * @param mode DestroyMode context provided to the factory * * @throws Exception If the factory fails to destroy the pooled object * cleanly */ - private void destroy(final PooledObject<T> toDestroy) throws Exception { + private void destroy(final PooledObject<T> toDestroy, final DestroyMode mode) throws Exception { toDestroy.invalidate(); idleObjects.remove(toDestroy); allObjects.remove(new IdentityWrapper<>(toDestroy.getObject())); try { - factory.destroyObject(toDestroy); + factory.destroyObject(toDestroy, mode); } finally { destroyedCount.incrementAndGet(); createCount.decrementAndGet(); @@ -1043,13 +1062,13 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> * Recovers abandoned objects which have been checked out but * not used since longer than the removeAbandonedTimeout. * - * @param ac The configuration to use to identify abandoned objects + * @param abandonedConfig The configuration to use to identify abandoned objects */ - private void removeAbandoned(final AbandonedConfig ac) { + private void removeAbandoned(final AbandonedConfig abandonedConfig) { // Generate a list of abandoned objects to remove final long now = System.currentTimeMillis(); final long timeout = - now - (ac.getRemoveAbandonedTimeout() * 1000L); + now - (abandonedConfig.getRemoveAbandonedTimeout() * 1000L); final ArrayList<PooledObject<T>> remove = new ArrayList<>(); for (PooledObject<T> pooledObject : allObjects.values()) { synchronized (pooledObject) { @@ -1063,11 +1082,11 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> // Now remove the abandoned objects for (PooledObject<T> pooledObject : remove) { - if (ac.getLogAbandoned()) { - pooledObject.printStackTrace(ac.getLogWriter()); + if (abandonedConfig.getLogAbandoned()) { + pooledObject.printStackTrace(abandonedConfig.getLogWriter()); } try { - invalidateObject(pooledObject.getObject()); + invalidateObject(pooledObject.getObject(), DestroyMode.ABANDONED); } catch (final Exception e) { e.printStackTrace(); } @@ -1079,8 +1098,8 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T> @Override public void use(final T pooledObject) { - final AbandonedConfig ac = this.abandonedConfig; - if (ac != null && ac.getUseUsageTracking()) { + final AbandonedConfig abandonedCfg = this.abandonedConfig; + if (abandonedCfg != null && abandonedCfg.getUseUsageTracking()) { final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject)); wrapper.use(); } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 0a8762e..89e6c40 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -214,6 +214,10 @@ Update the packaged version of the Tomcat Native Library to 1.2.26. (markt) </update> + <add> + Update the internal fork of Apache Commons Pool to 2.9.1-SNAPSHOT + (2021-01-15). (markt) + </add> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org