Author: markt Date: Sun Apr 29 20:01:09 2012 New Revision: 1331984 URL: http://svn.apache.org/viewvc?rev=1331984&view=rev Log: Pull up maxTotal, blockWhenExhausted and the Evictor inner class. Still lots more to pull up.
Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java?rev=1331984&r1=1331983&r2=1331984&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java Sun Apr 29 20:01:09 2012 @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; import java.util.List; +import java.util.TimerTask; import java.util.concurrent.atomic.AtomicInteger; import javax.management.ListenerNotFoundException; @@ -44,32 +45,43 @@ public abstract class BaseGenericObjectP // Constants /** * Name of the JMX notification broadcast when the pool implementation - * swallows an {@link Exception}. + * swallows an {@link Exception}. */ public static final String NOTIFICATION_SWALLOWED_EXCEPTION = "SWALLOWED_EXCEPTION"; private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10; - + // Configuration attributes - // None as yet - - // Internal state attributes + private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; + private volatile boolean blockWhenExhausted = + GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; + + + // Internal (primarily state) attributes volatile boolean closed = false; - + + /** + * Class loader for evictor thread to use since in a J2EE or similar + * environment the context class loader for the evictor thread may have + * visibility of the correct factory. See POOL-161. + */ + private final ClassLoader factoryClassLoader; + + // Monitoring (primarily JMX) attributes private final NotificationBroadcasterSupport jmxNotificationSupport; private final String creationStackTrace; private final Deque<String> swallowedExceptions = new LinkedList<String>(); private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0); - + public BaseGenericObjectPool(BaseObjectPoolConfig config) { if (config.getJmxEnabled()) { this.jmxNotificationSupport = new NotificationBroadcasterSupport(); } else { this.jmxNotificationSupport = null; } - + // Populate the swallowed exceptions queue for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) { swallowedExceptions.add(null); @@ -77,9 +89,69 @@ public abstract class BaseGenericObjectP // Populate the creation stack trace this.creationStackTrace = getStackTrace(new Exception()); + + // save the current CCL to be used later by the evictor Thread + factoryClassLoader = Thread.currentThread().getContextClassLoader(); + } + + + /** + * Returns the maximum number of objects that can be allocated by the pool + * (checked out to clients, or idle awaiting checkout) at a given time. When + * non-positive, there is no limit to the number of objects that can be + * managed by the pool at one time. + * + * @return the cap on the total number of object instances managed by the + * pool. + * @see #setMaxTotal + */ + public int getMaxTotal() { + return maxTotal; + } + + /** + * Sets the cap on the number of objects that can be allocated by the pool + * (checked out to clients, or idle awaiting checkout) at a given time. Use + * a negative value for no limit. + * + * @param maxTotal The cap on the total number of object instances managed + * by the pool. Negative values mean that there is no limit + * to the number of objects allocated by the pool. + * @see #getMaxTotal + */ + public void setMaxTotal(int maxTotal) { + this.maxTotal = maxTotal; + } + + /** + * Returns whether to block when the <code>borrowObject()</code> method is + * invoked when the pool is exhausted (the maximum number of "active" + * objects has been reached). + * + * @return <code>true</code> if <code>borrowObject()</code> should block + * when the pool is exhausted + * @see #setBlockWhenExhausted + */ + public boolean getBlockWhenExhausted() { + return blockWhenExhausted; } /** + * Sets whether to block when the <code>borrowObject()</code> method is + * invoked when the pool is exhausted (the maximum number of "active" + * objects has been reached). + * + * @param blockWhenExhausted <code>true</code> if + * <code>borrowObject()</code> should block + * when the pool is exhausted + * @see #getBlockWhenExhausted + */ + public void setBlockWhenExhausted(boolean blockWhenExhausted) { + this.blockWhenExhausted = blockWhenExhausted; + } + + + /** * Closes the pool destroys the remaining idle objects and, if registered in * JMX, deregisters it. */ @@ -92,12 +164,23 @@ public abstract class BaseGenericObjectP public final boolean isClosed() { return closed; } - - + + /** + * <p>Perform <code>numTests</code> idle object eviction tests, evicting + * examined objects that meet the criteria for eviction. If + * <code>testWhileIdle</code> is true, examined objects are validated + * when visited (and removed if invalid); otherwise only objects that + * have been idle for more than <code>minEvicableIdleTimeMillis</code> + * are removed.</p> + * + * @throws Exception when there is a problem evicting idle objects. + */ + public abstract void evict() throws Exception; + /** * Throws an <code>IllegalStateException</code> if called when the pool has * been closed. - * + * * @throws IllegalStateException if this pool has been closed. * @see #isClosed() */ @@ -107,22 +190,24 @@ public abstract class BaseGenericObjectP } } - + protected abstract void ensureMinIdle() throws Exception; + + // Monitoring (primarily JMX) related methods - + /** * Provides the name under which the pool has been registered with the * platform MBean server or <code>null</code> if the pool has not been * registered. */ public abstract ObjectName getJmxName(); - + /** * Provides the stack trace for the call that created this pool. JMX * registration may trigger a memory leak so it is important that pools are * deregistered when no longer used by calling the {@link #close()} method. * This method is provided to assist with identifying code that creates but - * does not close it thereby creating a memory leak. + * does not close it thereby creating a memory leak. */ public String getCreationStackTrace() { return creationStackTrace; @@ -145,7 +230,7 @@ public abstract class BaseGenericObjectP protected final NotificationBroadcasterSupport getJmxNotificationSupport() { return jmxNotificationSupport; } - + protected String getStackTrace(Exception e) { // Need the exception in string form to prevent the retention of // references to classes in the stack trace that could trigger a memory @@ -155,7 +240,7 @@ public abstract class BaseGenericObjectP e.printStackTrace(pw); return w.toString(); } - + protected void swallowException(Exception e) { String msg = getStackTrace(e); @@ -175,7 +260,7 @@ public abstract class BaseGenericObjectP // Implement NotificationEmitter interface - + @Override public final void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) @@ -218,4 +303,53 @@ public abstract class BaseGenericObjectP jmxNotificationSupport.removeNotificationListener( listener, filter, handback); } + + + // Inner classes + + /** + * The idle object evictor {@link TimerTask}. + * + * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis + */ + protected class Evictor extends TimerTask { + /** + * Run pool maintenance. Evict objects qualifying for eviction and then + * ensure that the minimum number of idle instances are available. + * Since the Timer that invokes Evictors is shared for all Pools but + * pools may exist in different class loaders, the Evictor ensures that + * any actions taken are under the class loader of the factory + * associated with the pool. + */ + @Override + public void run() { + ClassLoader savedClassLoader = + Thread.currentThread().getContextClassLoader(); + try { + // set the class loader for the factory + Thread.currentThread().setContextClassLoader( + factoryClassLoader); + + //Evict from the pool + try { + evict(); + } catch(Exception e) { + // ignored + } catch(OutOfMemoryError oome) { + // Log problem but give evictor thread a chance to continue + // in case error is recoverable + oome.printStackTrace(System.err); + } + //Re-create idle instances. + try { + ensureMinIdle(); + } catch (Exception e) { + // ignored + } + } finally { + // restore the previous CCL + Thread.currentThread().setContextClassLoader(savedClassLoader); + } + } + } } Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java?rev=1331984&r1=1331983&r2=1331984&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java Sun Apr 29 20:01:09 2012 @@ -220,8 +220,6 @@ public class GenericKeyedObjectPool<K,T> GenericKeyedObjectPoolConfig config) { super(config); this.factory = factory; - // save the current CCL to be used later by the evictor Thread - factoryClassLoader = Thread.currentThread().getContextClassLoader(); setConfig(config); @@ -294,59 +292,6 @@ public class GenericKeyedObjectPool<K,T> } /** - * Returns the overall maximum number of objects (across pools) that can - * exist at one time. A negative value indicates no limit. - * @return the maximum number of instances in circulation at one time. - * @see #setMaxTotal - */ - @Override - public int getMaxTotal() { - return maxTotal; - } - - /** - * Sets the cap on the total number of instances from all pools combined. - * When <code>maxTotal</code> is set to a - * positive value and {@link #borrowObject borrowObject} is invoked - * when at the limit with no idle instances available, an attempt is made to - * create room by clearing the oldest 15% of the elements from the keyed - * pools. - * - * @param maxTotal The cap on the total number of instances across pools. - * Use a negative value for no limit. - * @see #getMaxTotal - */ - public void setMaxTotal(int maxTotal) { - this.maxTotal = maxTotal; - } - - /** - * Returns whether to block when the {@link #borrowObject} method - * is invoked when the pool is exhausted (the maximum number - * of "active" objects has been reached). - * - * @return true if the pool should block - * @see #setBlockWhenExhausted - */ - @Override - public boolean getBlockWhenExhausted() { - return blockWhenExhausted; - } - - /** - * Sets whether to block when the {@link #borrowObject} method - * is invoked when the pool is exhausted (the maximum number - * of "active" objects has been reached). - * - * @param shouldBlock true if the pool should block - * @see #getBlockWhenExhausted - */ - public void setBlockWhenExhausted(boolean shouldBlock) { - blockWhenExhausted = shouldBlock; - } - - - /** * Returns the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the @@ -785,6 +730,12 @@ public class GenericKeyedObjectPool<K,T> * The length of time that this method will block when {@link #getBlockWhenExhausted()} is true * is determined by the {@link #getMaxWait() maxWait} property.</p> * + * When <code>maxTotal</code> is set to a + * positive value and {@link #borrowObject borrowObject} is invoked + * when at the limit with no idle instances available, an attempt is made to + * create room by clearing the oldest 15% of the elements from the keyed + * pools. + * * <p>When the pool is exhausted, multiple calling threads may be simultaneously blocked waiting for instances * to become available. As of pool 1.5, a "fairness" algorithm has been implemented to ensure that threads receive * available instances in request arrival order.</p> @@ -1346,19 +1297,13 @@ public class GenericKeyedObjectPool<K,T> /** - * <p>Perform <code>numTests</code> idle object eviction tests, evicting - * examined objects that meet the criteria for eviction. If - * <code>testWhileIdle</code> is true, examined objects are validated - * when visited (and removed if invalid); otherwise only objects that - * have been idle for more than <code>minEvicableIdletimeMillis</code> - * are removed.</p> - * - * <p>Successive activations of this method examine objects in keyed pools - * in sequence, cycling through the keys and examining objects in - * oldest-to-youngest order within the keyed pools.</p> - * - * @throws Exception when there is a problem evicting idle objects. + * {@inheritDoc} + * <p> + * Successive activations of this method examine objects in keyed pools in + * sequence, cycling through the keys and examining objects in + * oldest-to-youngest order within the keyed pools. */ + @Override public void evict() throws Exception { assertOpen(); @@ -1644,7 +1589,8 @@ public class GenericKeyedObjectPool<K,T> * @see #setMinIdlePerKey * @throws Exception If there was an error whilst creating the pooled objects. */ - private void ensureMinIdle() throws Exception { + @Override + protected void ensureMinIdle() throws Exception { int minIdle = getMinIdlePerKey(); if (minIdle < 1) { return; @@ -2071,50 +2017,6 @@ public class GenericKeyedObjectPool<K,T> } } - /** - * The idle object evictor {@link TimerTask}. - * - * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis - */ - private class Evictor extends TimerTask { - /** - * Run pool maintenance. Evict objects qualifying for eviction and then - * invoke {@link GenericKeyedObjectPool#ensureMinIdle()}. - * Since the Timer that invokes Evictors is shared for all Pools, we try - * to restore the ContextClassLoader that created the pool. - */ - @Override - public void run() { - ClassLoader savedClassLoader = - Thread.currentThread().getContextClassLoader(); - try { - // set the class loader for the factory - Thread.currentThread().setContextClassLoader( - factoryClassLoader); - - //Evict from the pool - try { - evict(); - } catch(Exception e) { - // ignored - } catch(OutOfMemoryError oome) { - // Log problem but give evictor thread a chance to continue in - // case error is recoverable - oome.printStackTrace(System.err); - } - //Re-create idle instances. - try { - ensureMinIdle(); - } catch (Exception e) { - // ignored - } - } finally { - // restore the previous CCL - Thread.currentThread().setContextClassLoader(savedClassLoader); - } - } - } - //--- configuration attributes --------------------------------------------- /** @@ -2141,13 +2043,6 @@ public class GenericKeyedObjectPool<K,T> GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; /** - * The cap on the total number of instances from the pool if non-positive. - * @see #setMaxTotal - * @see #getMaxTotal - */ - private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; - - /** * The maximum amount of time (in millis) the * {@link #borrowObject} method should block before throwing * an exception when the pool is exhausted and the @@ -2164,17 +2059,6 @@ public class GenericKeyedObjectPool<K,T> private long maxWait = GenericKeyedObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; /** - * When the {@link #borrowObject} method is invoked when the pool is - * exhausted (the maximum number of "active" objects has been reached) - * should the {@link #borrowObject} method block or not? - * - * @see #setBlockWhenExhausted - * @see #getBlockWhenExhausted - */ - private boolean blockWhenExhausted = - GenericKeyedObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; - - /** * When <code>true</code>, objects will be * {@link org.apache.commons.pool2.PoolableObjectFactory#validateObject validated} * before being returned by the {@link #borrowObject} @@ -2277,13 +2161,6 @@ public class GenericKeyedObjectPool<K,T> //--- internal attributes -------------------------------------------------- /** - * Class loader for evictor thread to use since in a J2EE or similar - * environment the context class loader for the evictor thread may have - * visibility of the correct factory. See POOL-161. - */ - private final ClassLoader factoryClassLoader; - - /** * My hash of pools (ObjectQueue). The list of keys <b>must</b> be kept in * step with {@link #poolKeyList} using {@link #keyLock} to ensure any * changes to the list of current keys is made in a thread-safe manner. Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1331984&r1=1331983&r2=1331984&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java Sun Apr 29 20:01:09 2012 @@ -185,8 +185,6 @@ public class GenericObjectPool<T> extend GenericObjectPoolConfig config) { super(config); this.factory = factory; - // save the current CCL to be used later by the evictor Thread - factoryClassLoader = Thread.currentThread().getContextClassLoader(); setConfig(config); @@ -235,61 +233,6 @@ public class GenericObjectPool<T> extend } /** - * Returns the maximum number of objects that can be allocated by the pool - * (checked out to clients, or idle awaiting checkout) at a given time. When - * non-positive, there is no limit to the number of objects that can be - * managed by the pool at one time. - * - * @return the cap on the total number of object instances managed by the - * pool. - * @see #setMaxTotal - */ - @Override - public int getMaxTotal() { - return maxTotal; - } - - /** - * Sets the cap on the number of objects that can be allocated by the pool - * (checked out to clients, or idle awaiting checkout) at a given time. Use - * a negative value for no limit. - * - * @param maxTotal - * The cap on the total number of object instances managed by the - * pool. Negative values mean that there is no limit to the - * number of objects allocated by the pool. - * @see #getMaxTotal - */ - public void setMaxTotal(int maxTotal) { - this.maxTotal = maxTotal; - } - - /** - * Returns whether to block when the {@link #borrowObject} method is - * invoked when the pool is exhausted (the maximum number of "active" - * objects has been reached). - * - * @return true if should block when the pool is exhuasted - * @see #setBlockWhenExhausted - */ - @Override - public boolean getBlockWhenExhausted() { - return blockWhenExhausted; - } - - /** - * Sets whether to block when the {@link #borrowObject} method is invoked - * when the pool is exhausted (the maximum number of "active" objects has - * been reached). - * - * @param blockWhenExhausted true if should block when the pool is exhausted - * @see #getBlockWhenExhausted - */ - public void setBlockWhenExhausted(boolean blockWhenExhausted) { - this.blockWhenExhausted = blockWhenExhausted; - } - - /** * Returns the maximum amount of time (in milliseconds) the * {@link #borrowObject} method should block before throwing an exception * when the pool is exhausted and the {@link #getBlockWhenExhausted} is true. @@ -1077,21 +1020,12 @@ public class GenericObjectPool<T> extend } /** - * <p> - * Perform <code>numTests</code> idle object eviction tests, evicting - * examined objects that meet the criteria for eviction. If - * <code>testWhileIdle</code> is true, examined objects are validated when - * visited (and removed if invalid); otherwise only objects that have been - * idle for more than <code>minEvicableIdletimeMillis</code> are removed. - * </p> + * {@inheritDoc} * <p> * Successive activations of this method examine objects in in sequence, * cycling through objects in oldest-to-youngest order. - * </p> - * - * @throws Exception - * if the pool is closed or eviction fails. */ + @Override public void evict() throws Exception { assertOpen(); @@ -1218,7 +1152,8 @@ public class GenericObjectPool<T> extend * @throws Exception * when {@link #addObject()} fails. */ - private void ensureMinIdle() throws Exception { + @Override + protected void ensureMinIdle() throws Exception { int minIdle = getMinIdle(); if (minIdle < 1) { return; @@ -1423,49 +1358,6 @@ public class GenericObjectPool<T> extend return oname; } - // --- inner classes ---------------------------------------------- - - /** - * The idle object evictor {@link TimerTask}. - * - * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis - */ - private class Evictor extends TimerTask { - /** - * Run pool maintenance. Evict objects qualifying for eviction and then - * invoke {@link GenericObjectPool#ensureMinIdle()}. - * Since the Timer that invokes Evictors is shared for all Pools, we try - * to restore the ContextClassLoader that created the pool. - */ - @Override - public void run() { - ClassLoader savedClassLoader = - Thread.currentThread().getContextClassLoader(); - try { - // set the class loader for the factory - Thread.currentThread().setContextClassLoader( - factoryClassLoader); - try { - evict(); - } catch (Exception e) { - // ignored - } catch (OutOfMemoryError oome) { - // Log problem but give evictor thread a chance to continue - // in case error is recoverable - oome.printStackTrace(System.err); - } - try { - ensureMinIdle(); - } catch (Exception e) { - e.printStackTrace(); - // ignored - } - } finally { - // restore the previous CCL - Thread.currentThread().setContextClassLoader(savedClassLoader); - } - } - } // --- configuration attributes -------------------------------------------- @@ -1486,15 +1378,6 @@ public class GenericObjectPool<T> extend private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; /** - * The cap on the total number of active instances from the pool. - * - * @see #setMaxTotal - * @see #getMaxTotal - */ - private volatile int maxTotal = - GenericObjectPoolConfig.DEFAULT_MAX_TOTAL; - - /** * The maximum amount of time (in millis) the {@link #borrowObject} method * should block before throwing an exception when the pool is exhausted and * {@link #getBlockWhenExhausted()} is true. @@ -1510,17 +1393,6 @@ public class GenericObjectPool<T> extend GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; /** - * When the {@link #borrowObject} method is invoked when the pool is - * exhausted (the maximum number of "active" objects has been reached) - * should the {@link #borrowObject} method block or not? - * - * @see #setBlockWhenExhausted - * @see #getBlockWhenExhausted - */ - private volatile boolean blockWhenExhausted = - GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; - - /** * When <tt>true</tt>, objects will be * {@link PoolableObjectFactory#validateObject validated} before being * returned by the {@link #borrowObject} method. If the object fails to @@ -1620,13 +1492,6 @@ public class GenericObjectPool<T> extend // --- internal attributes ------------------------------------------------- /** - * Class loader for evictor thread to use since in a J2EE or similar - * environment the context class loader for the evictor thread may have - * visibility of the correct factory. See POOL-161. - */ - private final ClassLoader factoryClassLoader; - - /** * All of the objects currently associated with this pool in any state. It * excludes objects that have been destroyed. The size of * {@link #allObjects} will always be less than or equal to {@link