| /* |
| * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/GenericObjectPool.java,v 1.1 2001/04/14 16:41:43 rwaldhoff Exp $ |
| * $Revision: 1.1 $ |
| * $Date: 2001/04/14 16:41:43 $ |
| * |
| * ==================================================================== |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 1999-2001 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, if |
| * any, must include the following acknowlegement: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowlegement may appear in the software itself, |
| * if and wherever such third-party acknowlegements normally appear. |
| * |
| * 4. The names "The Jakarta Project", "Commons", and "Apache Software |
| * Foundation" must not be used to endorse or promote products derived |
| * from this software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache" |
| * nor may "Apache" appear in their names without prior written |
| * permission of the Apache Group. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| */ |
| |
| package org.apache.commons.pool.impl; |
| |
| import org.apache.commons.pool.*; |
| import org.apache.commons.collections.CursorableLinkedList; |
| import org.apache.commons.collections.CursorableLinkedList.Cursor; |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| import java.util.Enumeration; |
| import java.util.EmptyStackException; |
| import java.util.ListIterator; |
| |
| /** |
| * A configurable {@link ObjectPool} implementation. |
| * <p> |
| * When coupled with the appropriate {@link PoolableObjectFactory}, |
| * <tt>GenericObjectPool</tt> provides robust pooling functionality for |
| * arbitrary objects. |
| * <p> |
| * A <tt>GenericObjectPool</tt> provides a number of configurable parameters: |
| * <ul> |
| * <li> |
| * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects that can |
| * be borrowed from the pool at one time. When non-positive, there |
| * is no limit to the number of objects that may be active at one time. |
| * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted. |
| * </li> |
| * <li> |
| * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can |
| * sit idle in the pool at any time. When non-positive, there |
| * is no limit to the number of objects that may be idle at one time. |
| * </li> |
| * <li> |
| * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the |
| * behaviour of the {@link #borrowObject} method when the pool is exhausted: |
| * <ul> |
| * <li> |
| * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is |
| * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw |
| * a {@link NoSuchElementException} |
| * </li> |
| * <li> |
| * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is |
| * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new |
| * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>} |
| * meaningless.) |
| * </li> |
| * <li> |
| * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} |
| * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block |
| * (invoke {@link Object#wait} until a new or idle object is available. |
| * If a positive {@link #setMaxWait <i>maxWait</i>} |
| * value is supplied, the {@link #borrowObject} will block for at |
| * most that many milliseconds, after which a {@link NoSuchElementException} |
| * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive, |
| * the {@link #borrowObject} method will block indefinitely. |
| * </li> |
| * </ul> |
| * </li> |
| * <li> |
| * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will |
| * attempt to validate each object before it is returned from the |
| * {@link #borrowObject} method. (Using the provided factory's |
| * {@link PoolableObjectFactory#validateObject} method.) Objects that fail |
| * to validate will be dropped from the pool, and a different object will |
| * be borrowed. |
| * </li> |
| * <li> |
| * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will |
| * attempt to validate each object before it is returned to the pool in the |
| * {@link #returnObject} method. (Using the provided factory's |
| * {@link PoolableObjectFactory#validateObject} |
| * method.) Objects that fail to validate will be dropped from the pool. |
| * </li> |
| * </ul> |
| * <p> |
| * Optionally, one may configure the pool to examine and possibly evict objects as they |
| * sit idle in the pool. This is performed by an "idle object eviction" thread, which |
| * runs asychronously. The idle object eviction thread may be configured using the |
| * following attributes: |
| * <ul> |
| * <li> |
| * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>} |
| * indicates how long the eviction thread should sleep before "runs" of examining |
| * idle objects. When non-positive, no eviction thread will be launched. |
| * </li> |
| * <li> |
| * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>} |
| * specifies the minimum amount of time that an object may sit idle in the pool |
| * before it is eligable for eviction due to idle time. When non-positive, no object |
| * will be dropped from the pool due to idle time alone. |
| * </li> |
| * <li> |
| * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle |
| * objects should be validated using the factory's |
| * {@link PoolableObjectFactory#validateObject} method. Objects |
| * that fail to validate will be dropped from the pool. |
| * </li> |
| * </ul> |
| * @see GenericKeyedObjectPool |
| * @author Rodney Waldhoff |
| * @version $Id: GenericObjectPool.java,v 1.1 2001/04/14 16:41:43 rwaldhoff Exp $ |
| */ |
| public class GenericObjectPool implements ObjectPool { |
| |
| //--- public constants ------------------------------------------- |
| |
| /** |
| * A "when exhausted action" type indicating that when the pool is |
| * exhausted (i.e., the maximum number of active objects has |
| * been reached), the {@link #borrowObject} |
| * method should fail, throwing a {@link NoSuchElementException}. |
| * @see #WHEN_EXHAUSTED_BLOCK |
| * @see #WHEN_EXHAUSTED_GROW |
| * @see #setWhenExhaustedAction |
| */ |
| public static final byte WHEN_EXHAUSTED_FAIL = 0; |
| |
| /** |
| * A "when exhausted action" type indicating that when the pool |
| * is exhausted (i.e., the maximum number |
| * of active objects has been reached), the {@link #borrowObject} |
| * method should block until a new object is available, or the |
| * {@link #getMaxWait maximum wait time} has been reached. |
| * @see #WHEN_EXHAUSTED_FAIL |
| * @see #WHEN_EXHAUSTED_GROW |
| * @see #setMaxWait |
| * @see #getMaxWait |
| * @see #setWhenExhaustedAction |
| */ |
| public static final byte WHEN_EXHAUSTED_BLOCK = 1; |
| |
| /** |
| * A "when exhausted action" type indicating that when the pool is |
| * exhausted (i.e., the maximum number |
| * of active objects has been reached), the {@link #borrowObject} |
| * method should simply create a new object anyway. |
| * @see #WHEN_EXHAUSTED_FAIL |
| * @see #WHEN_EXHAUSTED_GROW |
| * @see #setWhenExhaustedAction |
| */ |
| public static final byte WHEN_EXHAUSTED_GROW = 2; |
| |
| /** |
| * The default cap on the number of "sleeping" instances in the pool. |
| * @see #getMaxIdle |
| * @see #setMaxIdle |
| */ |
| public static final int DEFAULT_MAX_IDLE = 8; |
| |
| /** |
| * The default cap on the total number of active instances from the pool. |
| * @see #getMaxActive |
| */ |
| public static final int DEFAULT_MAX_ACTIVE = 8; |
| |
| /** |
| * The default "when exhausted action" for the pool. |
| * @see #WHEN_EXHAUSTED_BLOCK |
| * @see #WHEN_EXHAUSTED_FAIL |
| * @see #WHEN_EXHAUSTED_GROW |
| * @see #setWhenExhaustedAction |
| */ |
| public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK; |
| |
| /** |
| * The default maximum amount of time (in millis) the |
| * {@link #borrowObject} method should block before throwing |
| * an exception when the pool is exhausted and the |
| * {@link #getWhenExhaustedAction "when exhausted" action} is |
| * {@link #WHEN_EXHAUSTED_BLOCK}. |
| * @see #getMaxWait |
| * @see #setMaxWait |
| */ |
| public static final long DEFAULT_MAX_WAIT = -1L; |
| |
| /** |
| * The default "test on borrow" value. |
| * @see #getTestOnBorrow |
| * @see #setTestOnBorrow |
| */ |
| public static final boolean DEFAULT_TEST_ON_BORROW = false; |
| |
| /** |
| * The default "test on return" value. |
| * @see #getTestOnReturn |
| * @see #setTestOnReturn |
| */ |
| public static final boolean DEFAULT_TEST_ON_RETURN = false; |
| |
| /** |
| * The default "test while idle" value. |
| * @see #getTestWhileIdle |
| * @see #setTestWhileIdle |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public static final boolean DEFAULT_TEST_WHILE_IDLE = false; |
| |
| /** |
| * The default "time between eviction runs" value. |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; |
| |
| /** |
| * The default number of objects to examine per run in the |
| * idle object evictor. |
| * @see #getNumTestsPerEvictionRun |
| * @see #setNumTestsPerEvictionRun |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; |
| |
| /** |
| * The default value for {@link #getMinEvictableIdleTimeMillis}. |
| * @see #getMinEvictableIdleTimeMillis |
| * @see #setMinEvictableIdleTimeMillis |
| */ |
| public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; |
| |
| //--- constructors ----------------------------------------------- |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory) { |
| this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param config a non-<tt>null</tt> {@link GenericObjectPool.Config} describing my configuration |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) { |
| this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive) { |
| this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) |
| * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) { |
| this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) |
| * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) |
| * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow}) |
| * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) { |
| this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) |
| * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) |
| * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) { |
| this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction}) |
| * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait}) |
| * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle}) |
| * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow}) |
| * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) { |
| this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE); |
| } |
| |
| /** |
| * Create a new <tt>GenericObjectPool</tt> using the specified values. |
| * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects |
| * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive}) |
| * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction}) |
| * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait}) |
| * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle}) |
| * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow}) |
| * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn}) |
| * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis}) |
| * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun}) |
| * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis}) |
| * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle}) |
| */ |
| public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) { |
| _factory = factory; |
| _maxActive = maxActive; |
| switch(whenExhaustedAction) { |
| case WHEN_EXHAUSTED_BLOCK: |
| case WHEN_EXHAUSTED_FAIL: |
| case WHEN_EXHAUSTED_GROW: |
| _whenExhaustedAction = whenExhaustedAction; |
| break; |
| default: |
| throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); |
| } |
| _maxWait = maxWait; |
| _maxIdle = maxIdle; |
| _testOnBorrow = testOnBorrow; |
| _testOnReturn = testOnReturn; |
| _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| _numTestsPerEvictionRun = numTestsPerEvictionRun; |
| _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; |
| _testWhileIdle = testWhileIdle; |
| |
| _pool = new CursorableLinkedList(); |
| if(_timeBetweenEvictionRunsMillis > 0) { |
| _evictor = new Evictor(); |
| Thread t = new Thread(_evictor); |
| t.setDaemon(true); |
| t.start(); |
| } |
| } |
| |
| //--- public methods --------------------------------------------- |
| |
| //--- configuration methods -------------------------------------- |
| |
| /** |
| * Returns the cap on the total number of active instances from my pool. |
| * @return the cap on the total number of active instances from my pool. |
| * @see #setMaxActive |
| */ |
| public int getMaxActive() { |
| return _maxActive; |
| } |
| |
| /** |
| * Sets the cap on the total number of active instances from my pool. |
| * @param maxActive The cap on the total number of active instances from my pool. |
| * Use a negative value for an infinite number of instances. |
| * @see #getMaxActive |
| */ |
| public void setMaxActive(int maxActive) { |
| _maxActive = maxActive; |
| synchronized(this) { |
| notifyAll(); |
| } |
| } |
| |
| /** |
| * Returns the action to take when the {@link #borrowObject} method |
| * is invoked when the pool is exhausted (the maximum number |
| * of "active" objects has been reached). |
| * |
| * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW} |
| * @see #setWhenExhaustedAction |
| */ |
| public byte getWhenExhaustedAction() { |
| return _whenExhaustedAction; |
| } |
| |
| /** |
| * Sets the action to take when the {@link #borrowObject} method |
| * is invoked when the pool is exhausted (the maximum number |
| * of "active" objects has been reached). |
| * |
| * @param whenExhaustedAction the action code, which must be one of |
| * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL}, |
| * or {@link #WHEN_EXHAUSTED_GROW} |
| * @see #getWhenExhaustedAction |
| */ |
| public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) { |
| switch(whenExhaustedAction) { |
| case WHEN_EXHAUSTED_BLOCK: |
| case WHEN_EXHAUSTED_FAIL: |
| case WHEN_EXHAUSTED_GROW: |
| _whenExhaustedAction = whenExhaustedAction; |
| notifyAll(); |
| break; |
| default: |
| throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized."); |
| } |
| } |
| |
| |
| /** |
| * 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 #setWhenExhaustedAction "when exhausted" action} is |
| * {@link #WHEN_EXHAUSTED_BLOCK}. |
| * |
| * When less than 0, the {@link #borrowObject} method |
| * may block indefinitely. |
| * |
| * @see #setMaxWait |
| * @see #setWhenExhaustedAction |
| * @see #WHEN_EXHAUSTED_BLOCK |
| */ |
| public synchronized long getMaxWait() { |
| return _maxWait; |
| } |
| |
| /** |
| * Sets 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 #setWhenExhaustedAction "when exhausted" action} is |
| * {@link #WHEN_EXHAUSTED_BLOCK}. |
| * |
| * When less than 0, the {@link #borrowObject} method |
| * may block indefinitely. |
| * |
| * @see #getMaxWait |
| * @see #setWhenExhaustedAction |
| * @see #WHEN_EXHAUSTED_BLOCK |
| */ |
| public synchronized void setMaxWait(long maxWait) { |
| _maxWait = maxWait; |
| } |
| |
| /** |
| * Returns the cap on the number of "idle" instances in the pool. |
| * @return the cap on the number of "idle" instances in the pool. |
| * @see #setMaxIdle |
| */ |
| public int getMaxIdle() { |
| return _maxIdle; |
| } |
| |
| /** |
| * Sets the cap on the number of "idle" instances in the pool. |
| * @param maxIdle The cap on the number of "idle" instances in the pool. |
| * Use a negative value to indicate an unlimited number |
| * of idle instances. |
| * @see #getMaxIdle |
| */ |
| public void setMaxIdle(int maxIdle) { |
| _maxIdle = maxIdle; |
| synchronized(this) { |
| notifyAll(); |
| } |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned by the {@link #borrowObject} |
| * method. If the object fails to validate, |
| * it will be dropped from the pool, and we will attempt |
| * to borrow another. |
| * |
| * @see #setTestOnBorrow |
| */ |
| public boolean getTestOnBorrow() { |
| return _testOnBorrow; |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned by the {@link #borrowObject} |
| * method. If the object fails to validate, |
| * it will be dropped from the pool, and we will attempt |
| * to borrow another. |
| * |
| * @see #getTestOnBorrow |
| */ |
| public void setTestOnBorrow(boolean testOnBorrow) { |
| _testOnBorrow = testOnBorrow; |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned to the pool within the |
| * {@link #returnObject}. |
| * |
| * @see #setTestOnReturn |
| */ |
| public boolean getTestOnReturn() { |
| return _testOnReturn; |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned to the pool within the |
| * {@link #returnObject}. |
| * |
| * @see #getTestOnReturn |
| */ |
| public void setTestOnReturn(boolean testOnReturn) { |
| _testOnReturn = testOnReturn; |
| } |
| |
| /** |
| * Returns the number of milliseconds to sleep between runs of the |
| * idle object evictor thread. |
| * When non-positive, no idle object evictor thread will be |
| * run. |
| * |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public synchronized long getTimeBetweenEvictionRunsMillis() { |
| return _timeBetweenEvictionRunsMillis; |
| } |
| |
| /** |
| * Sets the number of milliseconds to sleep between runs of the |
| * idle object evictor thread. |
| * When non-positive, no idle object evictor thread will be |
| * run. |
| * |
| * @see #getTimeBetweenEvictionRunsMillis |
| */ |
| public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { |
| if(_timeBetweenEvictionRunsMillis > 0 && timeBetweenEvictionRunsMillis <= 0) { |
| _evictor.cancel(); |
| _evictor = null; |
| _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| } else if(_timeBetweenEvictionRunsMillis <= 0 && timeBetweenEvictionRunsMillis > 0) { |
| _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| _evictor = new Evictor(); |
| Thread t = new Thread(_evictor); |
| t.setDaemon(true); |
| t.start(); |
| } else { |
| _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| } |
| } |
| |
| /** |
| * Returns the number of objects to examine during each run of the |
| * idle object evictor thread (if any). |
| * |
| * @see #setNumTestsPerEvictionRun |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public int getNumTestsPerEvictionRun() { |
| return _numTestsPerEvictionRun; |
| } |
| |
| /** |
| * Sets the number of objects to examine during each run of the |
| * idle object evictor thread (if any). |
| * <p> |
| * When a negative value is supplied, <tt>ceil({@link #numIdle})/abs({@link #getNumTestsPerEvictionRun})</tt> |
| * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the |
| * idle objects will be tested per run. |
| * |
| * @see #getNumTestsPerEvictionRun |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { |
| _numTestsPerEvictionRun = numTestsPerEvictionRun; |
| } |
| |
| /** |
| * Returns the minimum amount of time an object may sit idle in the pool |
| * before it is eligable for eviction by the idle object evictor |
| * (if any). |
| * |
| * @see #setMinEvictableIdleTimeMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public synchronized long getMinEvictableIdleTimeMillis() { |
| return _minEvictableIdleTimeMillis; |
| } |
| |
| /** |
| * Sets the minimum amount of time an object may sit idle in the pool |
| * before it is eligable for eviction by the idle object evictor |
| * (if any). |
| * When non-positive, no objects will be evicted from the pool |
| * due to idle time alone. |
| * |
| * @see #getMinEvictableIdleTimeMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { |
| _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * by the idle object evictor (if any). If an object |
| * fails to validate, it will be dropped from the pool. |
| * |
| * @see #setTestWhileIdle |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public boolean getTestWhileIdle() { |
| return _testWhileIdle; |
| } |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * by the idle object evictor (if any). If an object |
| * fails to validate, it will be dropped from the pool. |
| * |
| * @see #getTestWhileIdle |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| public void setTestWhileIdle(boolean testWhileIdle) { |
| _testWhileIdle = testWhileIdle; |
| } |
| |
| /** |
| * Sets my configuration. |
| * @see GenericObjectPool.Config |
| */ |
| public synchronized void setConfig(GenericObjectPool.Config conf) { |
| setMaxIdle(conf.maxIdle); |
| setMaxActive(conf.maxActive); |
| setMaxWait(conf.maxWait); |
| setWhenExhaustedAction(conf.whenExhaustedAction); |
| setTestOnBorrow(conf.testOnBorrow); |
| setTestOnReturn(conf.testOnReturn); |
| setTestWhileIdle(conf.testWhileIdle); |
| setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun); |
| setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis); |
| setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis); |
| notifyAll(); |
| } |
| |
| //-- ObjectPool methods ------------------------------------------ |
| |
| public synchronized Object borrowObject() { |
| long starttime = System.currentTimeMillis(); |
| for(;;) { |
| ObjectTimestampPair pair = null; |
| // if there are any sleeping, just grab one of those |
| try { |
| pair = (ObjectTimestampPair)(_pool.removeFirst()); |
| } catch(NoSuchElementException e) { /* ignored */ |
| } |
| // otherwise |
| if(null == pair) { |
| // check if we can create one |
| // (note we know that the num sleeping is 0, else we wouldn't be here) |
| if(_maxActive > 0 && _numActive < _maxActive) { |
| Object obj = _factory.makeObject(); |
| pair = new ObjectTimestampPair(obj); |
| } else { |
| // the pool is exhausted |
| switch(_whenExhaustedAction) { |
| case WHEN_EXHAUSTED_GROW: |
| Object obj = _factory.makeObject(); |
| pair = new ObjectTimestampPair(obj); |
| break; |
| case WHEN_EXHAUSTED_FAIL: |
| throw new NoSuchElementException(); |
| case WHEN_EXHAUSTED_BLOCK: |
| try { |
| if(_maxWait <= 0) { |
| wait(); |
| } else { |
| wait(_maxWait); |
| } |
| } catch(InterruptedException e) { |
| // ignored |
| } |
| if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) { |
| throw new NoSuchElementException("Timeout waiting for idle object"); |
| } else { |
| continue; // keep looping |
| } |
| default: |
| throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized."); |
| } |
| } |
| } |
| _factory.activateObject(pair.value); |
| if(_testOnBorrow && !_factory.validateObject(pair.value)) { |
| try { |
| _factory.passivateObject(pair.value); |
| } catch(Exception e) { |
| ; // ignored, we're throwing it out anyway |
| } |
| _factory.destroyObject(pair.value); |
| } else { |
| _numActive++; |
| return pair.value; |
| } |
| } |
| } |
| |
| public synchronized void clear() throws UnsupportedOperationException { |
| Iterator it = _pool.iterator(); |
| while(it.hasNext()) { |
| _factory.destroyObject(((ObjectTimestampPair)(it.next())).value); |
| it.remove(); |
| } |
| _pool.clear(); |
| notifyAll(); // num sleeping has changed |
| } |
| |
| public int numActive() { |
| return _numActive; |
| } |
| |
| public int numIdle() { |
| return _pool.size(); |
| } |
| |
| public synchronized void returnObject(Object obj) { |
| _numActive--; |
| if(_maxIdle > 0 && (_pool.size() >= _maxIdle || (_testOnReturn && !_factory.validateObject(obj)))) { |
| try { |
| _factory.passivateObject(obj); |
| } catch(Exception e) { |
| ; // ignored, we're throwing it out anway |
| } |
| _factory.destroyObject(obj); |
| } else { |
| try { |
| _factory.passivateObject(obj); |
| _pool.addFirst(new ObjectTimestampPair(obj)); |
| } catch(Exception e) { |
| _factory.destroyObject(obj); |
| } |
| } |
| notifyAll(); // _numActive has changed |
| } |
| |
| synchronized public void close() { |
| clear(); |
| _pool = null; |
| _factory = null; |
| if(null != _evictor) { |
| _evictor.cancel(); |
| _evictor = null; |
| } |
| } |
| |
| synchronized public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { |
| if(0 < numActive()) { |
| throw new IllegalStateException("Objects are already active"); |
| } else { |
| clear(); |
| _factory = factory; |
| } |
| } |
| |
| //--- package methods -------------------------------------------- |
| |
| synchronized String debugInfo() { |
| StringBuffer buf = new StringBuffer(); |
| buf.append("Active: ").append(numActive()).append("\n"); |
| buf.append("Idle: ").append(numIdle()).append("\n"); |
| buf.append("Idle Objects:\n"); |
| Iterator it = _pool.iterator(); |
| long time = System.currentTimeMillis(); |
| while(it.hasNext()) { |
| ObjectTimestampPair pair = (ObjectTimestampPair)(it.next()); |
| buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n"); |
| } |
| return buf.toString(); |
| } |
| |
| //--- inner classes ---------------------------------------------- |
| |
| /** |
| * A simple "struct" encapsulating an object instance and a timestamp. |
| */ |
| class ObjectTimestampPair { |
| Object value; |
| long tstamp; |
| |
| ObjectTimestampPair(Object val) { |
| value = val; |
| tstamp = System.currentTimeMillis(); |
| } |
| |
| ObjectTimestampPair(Object val, long time) { |
| value = val; |
| tstamp = time; |
| } |
| } |
| |
| /** |
| * The idle object evictor thread. |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| class Evictor implements Runnable { |
| protected boolean _cancelled = false; |
| |
| void cancel() { |
| _cancelled = true; |
| } |
| |
| public void run() { |
| CursorableLinkedList.Cursor cursor = null; |
| while(!_cancelled) { |
| long sleeptime = 0L; |
| synchronized(GenericObjectPool.this) { |
| sleeptime = _timeBetweenEvictionRunsMillis; |
| } |
| try { |
| Thread.currentThread().sleep(_timeBetweenEvictionRunsMillis); |
| } catch(Exception e) { |
| ; // ignored |
| } |
| try { |
| synchronized(GenericObjectPool.this) { |
| if(!_pool.isEmpty()) { |
| if(null == cursor) { |
| cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size())); |
| } else if(!cursor.hasPrevious()) { |
| cursor.close(); |
| cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size())); |
| } |
| for(int i=0,m=getNumTests();i<m;i++) { |
| if(!cursor.hasPrevious()) { |
| cursor.close(); |
| cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size())); |
| } else { |
| ObjectTimestampPair pair = (ObjectTimestampPair)(cursor.previous()); |
| if(System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) { |
| try { |
| cursor.remove(); |
| _factory.destroyObject(pair.value); |
| } catch(Exception e) { |
| ; // ignored |
| } |
| } else if(_testWhileIdle) { |
| boolean active = false; |
| try { |
| _factory.activateObject(pair.value); |
| active = true; |
| } catch(Exception e) { |
| cursor.remove(); |
| try { |
| _factory.passivateObject(pair.value); |
| } catch(Exception ex) { |
| ; // ignored |
| } |
| _factory.destroyObject(pair.value); |
| } |
| if(active) { |
| if(!_factory.validateObject(pair.value)) { |
| cursor.remove(); |
| try { |
| _factory.passivateObject(pair.value); |
| } catch(Exception ex) { |
| ; // ignored |
| } |
| _factory.destroyObject(pair.value); |
| } else { |
| try { |
| _factory.passivateObject(pair.value); |
| } catch(Exception e) { |
| cursor.remove(); |
| _factory.destroyObject(pair.value); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } catch(Exception e) { |
| // ignored |
| } |
| } |
| if(null != cursor) { |
| cursor.close(); |
| } |
| } |
| |
| private int getNumTests() { |
| if(_numTestsPerEvictionRun >= 0) { |
| return _numTestsPerEvictionRun; |
| } else { |
| return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun))); |
| } |
| } |
| } |
| |
| /** |
| * A simple "struct" encapsulating the |
| * configuration information for a {@link GenericObjectPool}. |
| * @see GenericObjectPool#GenericObjectPool(org.apache.commons.pool.PoolableObjectFactory,org.apache.commons.pool.impl.GenericObjectPool.Config) |
| * @see GenericObjectPool#setConfig |
| */ |
| public static class Config { |
| public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE; |
| public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE; |
| public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT; |
| public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION; |
| public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW; |
| public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN; |
| public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE; |
| public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; |
| public int numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; |
| public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
| } |
| |
| //--- protected attributes --------------------------------------- |
| |
| /** |
| * The cap on the number of idle instances in the pool. |
| * @see #setMaxIdle |
| * @see #getMaxIdle |
| */ |
| protected int _maxIdle = DEFAULT_MAX_IDLE; |
| |
| /** |
| * The cap on the total number of active instances from the pool. |
| * @see #setMaxActive |
| * @see #getMaxActive |
| */ |
| protected int _maxActive = DEFAULT_MAX_ACTIVE; |
| |
| /** |
| * The maximum amount of time (in millis) the |
| * {@link #borrowObject} method should block before throwing |
| * an exception when the pool is exhausted and the |
| * {@link #getWhenExhaustedAction "when exhausted" action} is |
| * {@link #WHEN_EXHAUSTED_BLOCK}. |
| * |
| * When less than 0, the {@link #borrowObject} method |
| * may block indefinitely. |
| * |
| * @see #setMaxWait |
| * @see #getMaxWait |
| * @see #WHEN_EXHAUSTED_BLOCK |
| * @see #setWhenExhaustedAction |
| * @see #getWhenExhaustedAction |
| */ |
| protected long _maxWait = DEFAULT_MAX_WAIT; |
| |
| /** |
| * The action to take when the {@link #borrowObject} method |
| * is invoked when the pool is exhausted (the maximum number |
| * of "active" objects has been reached). |
| * |
| * @see #WHEN_EXHAUSTED_BLOCK |
| * @see #WHEN_EXHAUSTED_FAIL |
| * @see #WHEN_EXHAUSTED_GROW |
| * @see #DEFAULT_WHEN_EXHAUSTED_ACTION |
| * @see #setWhenExhaustedAction |
| * @see #getWhenExhaustedAction |
| */ |
| protected byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION; |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned by the {@link #borrowObject} |
| * method. If the object fails to validate, |
| * it will be dropped from the pool, and we will attempt |
| * to borrow another. |
| * |
| * @see #setTestOnBorrow |
| * @see #getTestOnBorrow |
| */ |
| protected boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW; |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * before being returned to the pool within the |
| * {@link #returnObject}. |
| * |
| * @see #getTestOnReturn |
| * @see #setTestOnReturn |
| */ |
| protected boolean _testOnReturn = DEFAULT_TEST_ON_RETURN; |
| |
| /** |
| * When <tt>true</tt>, objects will be |
| * {@link PoolableObjectFactory#validateObject validated} |
| * by the idle object evictor (if any). If an object |
| * fails to validate, it will be dropped from the pool. |
| * |
| * @see #setTestWhileIdle |
| * @see #getTestWhileIdle |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| protected boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE; |
| |
| /** |
| * The number of milliseconds to sleep between runs of the |
| * idle object evictor thread. |
| * When non-positive, no idle object evictor thread will be |
| * run. |
| * |
| * @see #setTimeBetweenEvictionRunsMillis |
| * @see #getTimeBetweenEvictionRunsMillis |
| */ |
| protected long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; |
| |
| /** |
| * The number of objects to examine during each run of the |
| * idle object evictor thread (if any). |
| * <p> |
| * When a negative value is supplied, <tt>ceil({@link #numIdle})/abs({@link #getNumTestsPerEvictionRun})</tt> |
| * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the |
| * idle objects will be tested per run. |
| * |
| * @see #setNumTestsPerEvictionRun |
| * @see #getNumTestsPerEvictionRun |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| protected int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; |
| |
| /** |
| * The minimum amount of time an object may sit idle in the pool |
| * before it is eligable for eviction by the idle object evictor |
| * (if any). |
| * When non-positive, no objects will be evicted from the pool |
| * due to idle time alone. |
| * |
| * @see #setMinEvictableIdleTimeMillis |
| * @see #getMinEvictableIdleTimeMillis |
| * @see #getTimeBetweenEvictionRunsMillis |
| * @see #setTimeBetweenEvictionRunsMillis |
| */ |
| protected long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
| |
| /** My pool. */ |
| protected CursorableLinkedList _pool = null; |
| |
| /** My {@link PoolableObjectFactory}. */ |
| protected PoolableObjectFactory _factory = null; |
| |
| /** |
| * The number of objects {@link #borrowObject} borrowed |
| * from the pool, but not yet returned. |
| */ |
| protected int _numActive = 0; |
| |
| /** |
| * My idle object eviction thread, if any. |
| */ |
| protected Evictor _evictor = null; |
| } |