tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject [tomcat] 02/02: Align fork of Commons Pool 2 with the 9.0.x copy
Date Fri, 03 May 2019 18:41:48 GMT
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 9c27bd13600fa2f6c40bcb6d5ff4ca0f5ca8cafd
Author: Mark Thomas <markt@apache.org>
AuthorDate: Fri May 3 19:40:24 2019 +0100

    Align fork of Commons Pool 2 with the 9.0.x copy
---
 java/org/apache/tomcat/dbcp/pool2/PoolUtils.java   | 47 ++++++++++++---------
 .../dbcp/pool2/impl/BaseGenericObjectPool.java     |  8 ++--
 .../tomcat/dbcp/pool2/impl/CallStackUtils.java     |  8 +---
 .../tomcat/dbcp/pool2/impl/EvictionTimer.java      | 35 +++++++++-------
 .../dbcp/pool2/impl/GenericKeyedObjectPool.java    | 26 ++++++------
 .../tomcat/dbcp/pool2/impl/GenericObjectPool.java  | 26 ++++++++++++
 java/org/apache/tomcat/dbcp/pool2/overview.html    | 49 ----------------------
 webapps/docs/changelog.xml                         |  4 ++
 8 files changed, 95 insertions(+), 108 deletions(-)

diff --git a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
index 4fb0aba..2494351 100644
--- a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
+++ b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
@@ -36,6 +36,13 @@ 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.";
+    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.";
+    private static final String MSG_NULL_POOL = "pool must not be null.";
+
     /**
      * Timer used to periodically check pools idle object count. Because a
      * {@link Timer} creates a {@link Thread}, an IODH is used.
@@ -101,10 +108,10 @@ public final class PoolUtils {
             final int minIdle, final long period)
             throws IllegalArgumentException {
         if (pool == null) {
-            throw new IllegalArgumentException("keyedPool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
         }
         if (minIdle < 0) {
-            throw new IllegalArgumentException("minIdle must be non-negative.");
+            throw new IllegalArgumentException(MSG_MIN_IDLE);
         }
         final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
         getMinIdleTimer().schedule(task, 0L, period);
@@ -142,13 +149,13 @@ public final class PoolUtils {
             final int minIdle, final long period)
             throws IllegalArgumentException {
         if (keyedPool == null) {
-            throw new IllegalArgumentException("keyedPool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
         }
         if (key == null) {
-            throw new IllegalArgumentException("key must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEY);
         }
         if (minIdle < 0) {
-            throw new IllegalArgumentException("minIdle must be non-negative.");
+            throw new IllegalArgumentException(MSG_MIN_IDLE);
         }
         final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
                 keyedPool, key, minIdle);
@@ -188,7 +195,7 @@ public final class PoolUtils {
             final int minIdle, final long period)
             throws IllegalArgumentException {
         if (keys == null) {
-            throw new IllegalArgumentException("keys must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYS);
         }
         final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
         final Iterator<K> iter = keys.iterator();
@@ -217,7 +224,7 @@ public final class PoolUtils {
     public static <T> void prefill(final ObjectPool<T> pool, final int count)
             throws Exception, IllegalArgumentException {
         if (pool == null) {
-            throw new IllegalArgumentException("pool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_POOL);
         }
         for (int i = 0; i < count; i++) {
             pool.addObject();
@@ -246,10 +253,10 @@ public final class PoolUtils {
             final K key, final int count) throws Exception,
             IllegalArgumentException {
         if (keyedPool == null) {
-            throw new IllegalArgumentException("keyedPool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
         }
         if (key == null) {
-            throw new IllegalArgumentException("key must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEY);
         }
         for (int i = 0; i < count; i++) {
             keyedPool.addObject(key);
@@ -281,7 +288,7 @@ public final class PoolUtils {
             final Collection<K> keys, final int count) throws Exception,
             IllegalArgumentException {
         if (keys == null) {
-            throw new IllegalArgumentException("keys must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYS);
         }
         final Iterator<K> iter = keys.iterator();
         while (iter.hasNext()) {
@@ -308,7 +315,7 @@ public final class PoolUtils {
      */
     public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T>
pool) {
         if (pool == null) {
-            throw new IllegalArgumentException("pool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_POOL);
         }
         /*
          * assert !(pool instanceof GenericObjectPool) :
@@ -436,10 +443,10 @@ public final class PoolUtils {
     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool,
             final float factor) {
         if (pool == null) {
-            throw new IllegalArgumentException("pool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_POOL);
         }
         if (factor <= 0f) {
-            throw new IllegalArgumentException("factor must be positive.");
+            throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
         }
         return new ErodingObjectPool<>(pool, factor);
     }
@@ -538,10 +545,10 @@ public final class PoolUtils {
             final KeyedObjectPool<K, V> keyedPool, final float factor,
             final boolean perKey) {
         if (keyedPool == null) {
-            throw new IllegalArgumentException("keyedPool must not be null.");
+            throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
         }
         if (factor <= 0f) {
-            throw new IllegalArgumentException("factor must be positive.");
+            throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
         }
         if (perKey) {
             return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
@@ -587,7 +594,7 @@ public final class PoolUtils {
         ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, final int minIdle)
                 throws IllegalArgumentException {
             if (pool == null) {
-                throw new IllegalArgumentException("pool must not be null.");
+                throw new IllegalArgumentException(MSG_NULL_POOL);
             }
             this.pool = pool;
             this.minIdle = minIdle;
@@ -665,7 +672,7 @@ public final class PoolUtils {
                 final K key, final int minIdle) throws IllegalArgumentException {
             if (keyedPool == null) {
                 throw new IllegalArgumentException(
-                        "keyedPool must not be null.");
+                        MSG_NULL_KEYED_POOL);
             }
             this.keyedPool = keyedPool;
             this.key = key;
@@ -747,7 +754,7 @@ public final class PoolUtils {
         SynchronizedObjectPool(final ObjectPool<T> pool)
                 throws IllegalArgumentException {
             if (pool == null) {
-                throw new IllegalArgumentException("pool must not be null.");
+                throw new IllegalArgumentException(MSG_NULL_POOL);
             }
             this.pool = pool;
         }
@@ -924,7 +931,7 @@ public final class PoolUtils {
                 throws IllegalArgumentException {
             if (keyedPool == null) {
                 throw new IllegalArgumentException(
-                        "keyedPool must not be null.");
+                        MSG_NULL_KEYED_POOL);
             }
             this.keyedPool = keyedPool;
         }
@@ -1605,7 +1612,7 @@ public final class PoolUtils {
                 final ErodingFactor erodingFactor) {
             if (keyedPool == null) {
                 throw new IllegalArgumentException(
-                        "keyedPool must not be null.");
+                        MSG_NULL_KEYED_POOL);
             }
             this.keyedPool = keyedPool;
             this.erodingFactor = erodingFactor;
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
index 0de61d6..448c4a7 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
@@ -772,11 +772,9 @@ public abstract class BaseGenericObjectPool<T> extends BaseObject
{
      */
     final void startEvictor(final long delay) {
         synchronized (evictionLock) {
-            if (null != evictor) {
-                EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
-                evictor = null;
-                evictionIterator = null;
-            }
+            EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
+            evictor = null;
+            evictionIterator = null;
             if (delay > 0) {
                 evictor = new Evictor();
                 EvictionTimer.schedule(evictor, delay, delay);
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java b/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
index d5089c3..871f311 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
@@ -25,12 +25,6 @@ import java.security.AccessControlException;
  */
 public final class CallStackUtils {
 
-    private static final boolean CAN_CREATE_SECURITY_MANAGER;
-
-    static {
-        CAN_CREATE_SECURITY_MANAGER = canCreateSecurityManager();
-    }
-
     /**
      * @return {@code true} if it is able to create a security manager in the current environment,
{@code false}
      *         otherwise.
@@ -76,7 +70,7 @@ public final class CallStackUtils {
     public static CallStack newCallStack(final String messageFormat,
                                          final boolean useTimestamp,
                                          final boolean requireFullStackTrace) {
-        return CAN_CREATE_SECURITY_MANAGER && !requireFullStackTrace
+        return canCreateSecurityManager() && !requireFullStackTrace
             ? new SecurityManagerCallStack(messageFormat, useTimestamp)
             : new ThrowableCallStack(messageFormat, useTimestamp);
     }
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
index b483dc3..f034c38 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
@@ -24,18 +24,20 @@ import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 
 /**
- * Provides a shared idle object eviction timer for all pools. This class is
- * currently implemented using {@link ScheduledThreadPoolExecutor}. This
- * implementation may change in any future release. This class keeps track of
- * how many pools are using it. If no pools are using the timer, it is cancelled.
- * This prevents a thread being left running which, in application server
- * environments, can lead to memory leads and/or prevent applications from
- * shutting down or reloading cleanly.
+ * Provides a shared idle object eviction timer for all pools.
  * <p>
- * This class has package scope to prevent its inclusion in the pool public API.
- * The class declaration below should *not* be changed to public.
+ * This class is currently implemented using {@link ScheduledThreadPoolExecutor}. This implementation
may change in any
+ * future release. This class keeps track of how many pools are using it. If no pools are
using the timer, it is
+ * cancelled. This prevents a thread being left running which, in application server environments,
can lead to memory
+ * leads and/or prevent applications from shutting down or reloading cleanly.
+ * </p>
+ * <p>
+ * This class has package scope to prevent its inclusion in the pool public API. The class
declaration below should
+ * *not* be changed to public.
+ * </p>
  * <p>
  * This class is intended to be thread-safe.
+ * </p>
  *
  * @since 2.0
  */
@@ -66,6 +68,7 @@ class EvictionTimer {
      * call to this method *must* call {@link #cancel(BaseGenericObjectPool.Evictor,long,TimeUnit)}
      * to cancel the task to prevent memory and/or thread leaks in application
      * server environments.
+     *
      * @param task      Task to be scheduled
      * @param delay     Delay in milliseconds before task is executed
      * @param period    Time in milliseconds between executions
@@ -84,16 +87,18 @@ class EvictionTimer {
     /**
      * Remove the specified eviction task from the timer.
      *
-     * @param task      Task to be cancelled
+     * @param evictor      Task to be cancelled
      * @param timeout   If the associated executor is no longer required, how
      *                  long should this thread wait for the executor to
      *                  terminate?
      * @param unit      The units for the specified timeout
      */
     static synchronized void cancel(
-            final BaseGenericObjectPool<?>.Evictor task, final long timeout, final
TimeUnit unit) {
-        task.cancel();
-        if (executor.getQueue().size() == 0) {
+            final BaseGenericObjectPool<?>.Evictor evictor, final long timeout, final
TimeUnit unit) {
+        if (evictor != null) {
+            evictor.cancel();
+        }
+        if (executor != null && executor.getQueue().isEmpty()) {
             executor.shutdown();
             try {
                 executor.awaitTermination(timeout, unit);
@@ -107,14 +112,14 @@ class EvictionTimer {
     }
 
     /**
-     * Thread factory that creates a thread, with the context class loader from this class.
+     * Thread factory that creates a daemon thread, with the context class loader from this
class.
      */
     private static class EvictorThreadFactory implements ThreadFactory {
 
         @Override
         public Thread newThread(final Runnable runnable) {
             final Thread thread = new Thread(null, runnable, "commons-pool-evictor-thread");
-
+            thread.setDaemon(true); // POOL-363 - Required for applications using Runtime.addShutdownHook().
--joshlandin 03.27.2019
             AccessController.doPrivileged(new PrivilegedAction<Void>() {
                 @Override
                 public Void run() {
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
index d9c9c8f..175631c 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
@@ -1145,26 +1145,28 @@ public class GenericKeyedObjectPool<K, T> extends BaseGenericObjectPool<T>
      * @param k The key to de-register
      */
     private void deregister(final K k) {
+        Lock lock = keyLock.readLock();
         ObjectDeque<T> objectDeque;
-
-        objectDeque = poolMap.get(k);
-        final long numInterested = objectDeque.getNumInterested().decrementAndGet();
-        if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
-            // Potential to remove key
-            final Lock writeLock = keyLock.writeLock();
-            writeLock.lock();
-            try {
-                if (objectDeque.getCreateCount().get() == 0 &&
-                        objectDeque.getNumInterested().get() == 0) {
+        try {
+            lock.lock();
+            objectDeque = poolMap.get(k);
+            final long numInterested = objectDeque.getNumInterested().decrementAndGet();
+            if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
+                // Potential to remove key
+                // Upgrade to write lock
+                lock.unlock();
+                lock = keyLock.writeLock();
+                lock.lock();
+                if (objectDeque.getCreateCount().get() == 0 && objectDeque.getNumInterested().get()
== 0) {
                     // NOTE: Keys must always be removed from both poolMap and
                     //       poolKeyList at the same time while protected by
                     //       keyLock.writeLock()
                     poolMap.remove(k);
                     poolKeyList.remove(k);
                 }
-            } finally {
-                writeLock.unlock();
             }
+        } finally {
+            lock.unlock();
         }
     }
 
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
index 15b6d6d..04fdd79 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
@@ -181,6 +181,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * <p>
      * If the configured value of minIdle is greater than the configured value
      * for maxIdle then the value of maxIdle will be used instead.
+     * </p>
      *
      * @param minIdle
      *            The minimum number of objects.
@@ -202,6 +203,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * <p>
      * If the configured value of minIdle is greater than the configured value
      * for maxIdle then the value of maxIdle will be used instead.
+     * </p>
      *
      * @return The minimum number of objects.
      *
@@ -339,6 +341,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * borrowObject}({@link #getMaxWaitMillis()})</code>.
      * <p>
      * {@inheritDoc}
+     * </p>
      */
     @Override
     public T borrowObject() throws Exception {
@@ -356,6 +359,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * instance is destroyed and the next available instance is examined. This
      * continues until either a valid instance is returned or there are no more
      * idle instances available.
+     * </p>
      * <p>
      * If there are no idle instances available in the pool, behavior depends on
      * the {@link #getMaxTotal() maxTotal}, (if applicable)
@@ -365,6 +369,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * instance is created, activated and (if applicable) validated and returned
      * to the caller. If validation fails, a <code>NoSuchElementException</code>
      * is thrown.
+     * </p>
      * <p>
      * If the pool is exhausted (no available idle instances and no capacity to
      * create new ones), this method will either block (if
@@ -374,11 +379,13 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * method will block when {@link #getBlockWhenExhausted()} is true is
      * determined by the value passed in to the <code>borrowMaxWaitMillis</code>
      * parameter.
+     * </p>
      * <p>
      * When the pool is exhausted, multiple calling threads may be
      * simultaneously blocked waiting for instances to become available. A
      * "fairness" algorithm has been implemented to ensure that threads receive
      * available instances in request arrival order.
+     * </p>
      *
      * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
      *                            to become available
@@ -496,14 +503,17 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
      * number of idle instances has reached this value, the returning instance
      * is destroyed.
+     * </p>
      * <p>
      * If {@link #getTestOnReturn() testOnReturn} == true, the returning
      * instance is validated before being returned to the idle instance pool. In
      * this case, if validation fails, the instance is destroyed.
+     * </p>
      * <p>
      * Exceptions encountered destroying objects for any reason are swallowed
      * but notified via a
      * {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.
+     * </p>
      */
     @Override
     public void returnObject(final T obj) {
@@ -587,6 +597,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * <p>
      * Activation of this method decrements the active count and attempts to
      * destroy the instance.
+     * </p>
      *
      * @throws Exception             if an exception occurs destroying the
      *                               object
@@ -617,6 +628,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * idle instance.
      * <p>
      * Implementation notes:
+     * </p>
      * <ul>
      * <li>This method does not destroy or effect in any way instances that are
      * checked out of the pool when it is invoked.</li>
@@ -659,6 +671,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * objects destroyed on return.
      * <p>
      * Destroys idle instances in the pool by invoking {@link #clear()}.
+     * </p>
      */
     @Override
     public void close() {
@@ -691,6 +704,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * <p>
      * Successive activations of this method examine objects in sequence,
      * cycling through objects in oldest-to-youngest order.
+     * </p>
      */
     @Override
     public void evict() throws Exception {
@@ -811,6 +825,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * <p>
      * If there are {@link #getMaxTotal()} objects already in circulation
      * or in process of being created, this method returns null.
+     * </p>
      *
      * @return The new wrapped pooled object
      *
@@ -915,6 +930,15 @@ 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
@@ -929,6 +953,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * or the total number of objects (idle, checked out, or being created) reaches
      * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
      * there are threads waiting to check out instances from the pool.
+     * </p>
      *
      * @param idleCount the number of idle instances desired
      * @param always true means create instances even if the pool has no threads waiting
@@ -1115,6 +1140,7 @@ public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
      * JMX. That means it won't be invoked unless the explicitly requested
      * whereas all attributes will be automatically requested when viewing the
      * attributes for an object in a tool like JConsole.
+     * </p>
      *
      * @return Information grouped on all the objects in the pool
      */
diff --git a/java/org/apache/tomcat/dbcp/pool2/overview.html b/java/org/apache/tomcat/dbcp/pool2/overview.html
deleted file mode 100644
index b301d1d..0000000
--- a/java/org/apache/tomcat/dbcp/pool2/overview.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!--
- 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.
--->
-<html>
-   <head>
-      <title>Overview of the org.apache.commons.pool2 component</title>
-   </head>
-   <body>
-      <p>
-         Generic Object pooling API with several implementations.
-      </p>
-      <p>
-         The <code>org.apache.commons.pool2</code> package defines a simple
-         interface for a pool of object instances, and a handful of base
-         classes that may be useful when creating pool implementations.
-         The API supports pooling of unique objects which can be requested
-         via a key as well as pools where all objects are equivalent.
-      </p>
-      <p>
-         The <code>org.apache.commons.pool2.impl</code> package contains
-         several pool implementations.
-         {@link org.apache.commons.pool2.impl.GenericObjectPool
-         GenericObjectPool} has many configuration options and can support
-         a limited set of objects such as would be useful in a database
-         connection pool.
-         {@link org.apache.commons.pool2.impl.SoftReferenceObjectPool
-         SoftReferenceObjectPool} has no limit on the number of objects in the
-         pool, but the garbage collector can remove idle objects from the pool
-         as needed.  There is also a keyed version of
-         {@link org.apache.commons.pool2.impl.GenericObjectPool
-         GenericObjectPool},
-         {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
-         GenericKeyedObjectPool}
-      </p>
-   </body>
-</html>
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 37addb6..565a3ed 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -131,6 +131,10 @@
         (2019-04-24) to pick up some clean-up and enhancements less the JDBC 4.2
         related changes that require Java 8. (markt)
       </update>
+      <update>
+        Update the internal fork of Apache Commons Pool 2 to 0664f4d
+        (2019-04-30) to pick up some enhancements and bug fixes. (markt)
+      </update>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message