001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.pool.impl;
019    
020    import java.util.HashMap;
021    import java.util.Iterator;
022    import java.util.Map;
023    import java.util.NoSuchElementException;
024    import java.util.Set;
025    import java.util.TreeMap;
026    import java.util.TimerTask;
027    
028    import org.apache.commons.pool.BaseKeyedObjectPool;
029    import org.apache.commons.pool.KeyedObjectPool;
030    import org.apache.commons.pool.KeyedPoolableObjectFactory;
031    
032    /**
033     * A configurable <code>KeyedObjectPool</code> implementation modifying the standard
034     * version coming with commons-pool to not lock each and every pool access which led
035     * to scalability issues and even deadlocks (TAPESTRY-2530, TAPESTRY-2382).
036     * TODO: switch back to the standard version once it works better.
037     *
038     * <p>
039     * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
040     * <code>GenericKeyedObjectPool</code> provides robust pooling functionality for
041     * keyed objects. A <code>GenericKeyedObjectPool</code> can be viewed as a map
042     * of pools, keyed on the (unique) key values provided to the 
043     * {@link #preparePool preparePool}, {@link #addObject addObject} or
044     * {@link #borrowObject borrowObject} methods. Each time a new key value is
045     * provided to one of these methods, a new pool is created under the given key
046     * to be managed by the containing <code>GenericKeyedObjectPool.</code>
047     * </p>
048     * <p>A <code>GenericKeyedObjectPool</code> provides a number of configurable
049     * parameters:</p>
050     * <ul>
051     *  <li>
052     *    {@link #setMaxActive maxActive} controls the maximum number of objects
053     *    (per key) that can be borrowed from the pool at one time.  When
054     *    non-positive, there is no limit to the number of objects per key.
055     *    When {@link #setMaxActive maxActive} is exceeded, the keyed pool is said
056     *    to be exhausted.  The default setting for this parameter is 8.
057     *  </li>
058     *  <li>
059     *    {@link #setMaxTotal maxTotal} sets a global limit on the number of objects
060     *    that can be in circulation (active or idle) within the combined set of
061     *    pools.  When non-positive, there is no limit to the total number of
062     *    objects in circulation. When {@link #setMaxTotal maxTotal} is exceeded,
063     *    all keyed pools are exhausted. When <code>maxTotal</code> is set to a
064     *    positive value and {@link #borrowObject borrowObject} is invoked
065     *    when at the limit with no idle instances available, an attempt is made to
066     *    create room by clearing the oldest 15% of the elements from the keyed
067     *    pools. The default setting for this parameter is -1 (no limit).
068     *  </li>
069     *  <li>
070     *    {@link #setMaxIdle maxIdle} controls the maximum number of objects that can
071     *    sit idle in the pool (per key) at any time.  When negative, there
072     *    is no limit to the number of objects that may be idle per key. The
073     *    default setting for this parameter is 8.
074     *  </li>
075     *  <li>
076     *    {@link #setWhenExhaustedAction whenExhaustedAction} specifies the
077     *    behavior of the {@link #borrowObject borrowObject} method when a keyed
078     *    pool is exhausted:
079     *    <ul>
080     *    <li>
081     *      When {@link #setWhenExhaustedAction whenExhaustedAction} is
082     *      {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject borrowObject} will throw
083     *      a {@link NoSuchElementException}
084     *    </li>
085     *    <li>
086     *      When {@link #setWhenExhaustedAction whenExhaustedAction} is
087     *      {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject borrowObject} will create a new
088     *      object and return it (essentially making {@link #setMaxActive maxActive}
089     *      meaningless.)
090     *    </li>
091     *    <li>
092     *      When {@link #setWhenExhaustedAction whenExhaustedAction}
093     *      is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject borrowObject} will block
094     *      (invoke {@link Object#wait() wait} until a new or idle object is available.
095     *      If a positive {@link #setMaxWait maxWait}
096     *      value is supplied, the {@link #borrowObject borrowObject} will block for at
097     *      most that many milliseconds, after which a {@link NoSuchElementException}
098     *      will be thrown.  If {@link #setMaxWait maxWait} is non-positive,
099     *      the {@link #borrowObject borrowObject} method will block indefinitely.
100     *    </li>
101     *    </ul>
102     *    The default <code>whenExhaustedAction</code> setting is
103     *    {@link #WHEN_EXHAUSTED_BLOCK}.
104     *  </li>
105     *  <li>
106     *    When {@link #setTestOnBorrow testOnBorrow} is set, the pool will
107     *    attempt to validate each object before it is returned from the
108     *    {@link #borrowObject borrowObject} method. (Using the provided factory's
109     *    {@link KeyedPoolableObjectFactory#validateObject validateObject} method.)
110     *    Objects that fail to validate will be dropped from the pool, and a
111     *    different object will be borrowed. The default setting for this parameter
112     *    is <code>false.</code>
113     *  </li>
114     *  <li>
115     *    When {@link #setTestOnReturn testOnReturn} is set, the pool will
116     *    attempt to validate each object before it is returned to the pool in the
117     *    {@link #returnObject returnObject} method. (Using the provided factory's
118     *    {@link KeyedPoolableObjectFactory#validateObject validateObject}
119     *    method.)  Objects that fail to validate will be dropped from the pool.
120     *    The default setting for this parameter is <code>false.</code>
121     *  </li>
122     * </ul>
123     * <p>
124     * Optionally, one may configure the pool to examine and possibly evict objects
125     * as they sit idle in the pool and to ensure that a minimum number of idle
126     * objects is maintained for each key. This is performed by an
127     * "idle object eviction" thread, which runs asynchronously. Caution should be
128     * used when configuring this optional feature. Eviction runs require an
129     * exclusive synchronization lock on the pool, so if they run too frequently
130     * and / or incur excessive latency when creating, destroying or validating
131     * object instances, performance issues may result.  The idle object eviction
132     * thread may be configured using the following attributes:
133     * <ul>
134     *  <li>
135     *   {@link #setTimeBetweenEvictionRunsMillis timeBetweenEvictionRunsMillis}
136     *   indicates how long the eviction thread should sleep before "runs" of examining
137     *   idle objects.  When non-positive, no eviction thread will be launched. The
138     *   default setting for this parameter is -1 (i.e., by default, idle object
139     *   eviction is disabled).
140     *  </li>
141     *  <li>
142     *   {@link #setMinEvictableIdleTimeMillis minEvictableIdleTimeMillis}
143     *   specifies the minimum amount of time that an object may sit idle in the
144     *   pool before it is eligible for eviction due to idle time.  When
145     *   non-positive, no object will be dropped from the pool due to idle time
146     *   alone.  This setting has no effect unless 
147     *   <code>timeBetweenEvictionRunsMillis > 0.</code>  The default setting
148     *   for this parameter is 30 minutes.
149     *  </li>
150     *  <li>
151     *   {@link #setTestWhileIdle testWhileIdle} indicates whether or not idle
152     *   objects should be validated using the factory's
153     *   {@link KeyedPoolableObjectFactory#validateObject validateObject} method
154     *   during idle object eviction runs.  Objects that fail to validate will be
155     *   dropped from the pool. This setting has no effect unless 
156     *   <code>timeBetweenEvictionRunsMillis > 0.</code>  The default setting
157     *   for this parameter is <code>false.</code>
158     *  </li>
159     *  <li>
160     *    {@link #setMinIdle minIdle} sets a target value for the minimum number of
161     *    idle objects (per key) that should always be available. If this parameter
162     *    is set to a positive number and 
163     *    <code>timeBetweenEvictionRunsMillis > 0,</code> each time the idle object
164     *    eviction thread runs, it will try to create enough idle instances so that
165     *    there will be <code>minIdle</code> idle instances available under each
166     *    key. This parameter is also used by {@link #preparePool preparePool}
167     *    if <code>true</code> is provided as that method's
168     *    <code>populateImmediately</code> parameter. The default setting for this
169     *    parameter is 0.
170     *  </li>
171     * </ul>
172     * <p>
173     * The pools can be configured to behave as LIFO queues with respect to idle
174     * objects - always returning the most recently used object from the pool,
175     * or as FIFO queues, where borrowObject always returns the oldest object
176     * in the idle object pool.
177     * <ul>
178     *  <li>
179     *   {@link #setLifo <i>Lifo</i>}
180     *   determines whether or not the pools return idle objects in 
181     *   last-in-first-out order. The default setting for this parameter is 
182     *   <code>true.</code>
183     *  </li>
184     * </ul>
185     * <p>
186     * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}.  A
187     * non-<code>null</code> factory must be provided either as a constructor argument
188     * or via a call to {@link #setFactory setFactory} before the pool is used.
189     * </p>
190     * @see GenericObjectPool
191     * @author Rodney Waldhoff
192     * @author Dirk Verbeeck
193     * @author Sandy McArthur
194     * @version $Revision: 620830 $ $Date: 2008-02-12 16:41:58 +0100 (Di, 12 Feb 2008) $
195     * @since Pool 1.0
196     */
197    public class TapestryKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
198    
199        //--- public constants -------------------------------------------
200    
201        /**
202         * A "when exhausted action" type indicating that when the pool is
203         * exhausted (i.e., the maximum number of active objects has
204         * been reached), the {@link #borrowObject}
205         * method should fail, throwing a {@link NoSuchElementException}.
206         * @see #WHEN_EXHAUSTED_BLOCK
207         * @see #WHEN_EXHAUSTED_GROW
208         * @see #setWhenExhaustedAction
209         */
210        public static final byte WHEN_EXHAUSTED_FAIL   = 0;
211    
212        /**
213         * A "when exhausted action" type indicating that when the pool
214         * is exhausted (i.e., the maximum number
215         * of active objects has been reached), the {@link #borrowObject}
216         * method should block until a new object is available, or the
217         * {@link #getMaxWait maximum wait time} has been reached.
218         * @see #WHEN_EXHAUSTED_FAIL
219         * @see #WHEN_EXHAUSTED_GROW
220         * @see #setMaxWait
221         * @see #getMaxWait
222         * @see #setWhenExhaustedAction
223         */
224        public static final byte WHEN_EXHAUSTED_BLOCK  = 1;
225    
226        /**
227         * A "when exhausted action" type indicating that when the pool is
228         * exhausted (i.e., the maximum number
229         * of active objects has been reached), the {@link #borrowObject}
230         * method should simply create a new object anyway.
231         * @see #WHEN_EXHAUSTED_FAIL
232         * @see #WHEN_EXHAUSTED_GROW
233         * @see #setWhenExhaustedAction
234         */
235        public static final byte WHEN_EXHAUSTED_GROW   = 2;
236    
237        /**
238         * The default cap on the number of idle instances (per key) in the pool.
239         * @see #getMaxIdle
240         * @see #setMaxIdle
241         */
242        public static final int DEFAULT_MAX_IDLE  = 8;
243    
244        /**
245         * The default cap on the total number of active instances (per key)
246         * from the pool.
247         * @see #getMaxActive
248         * @see #setMaxActive
249         */
250        public static final int DEFAULT_MAX_ACTIVE  = 8;
251    
252        /**
253         * The default cap on the the overall maximum number of objects that can
254         * exist at one time.
255         * @see #getMaxTotal
256         * @see #setMaxTotal
257         */
258        public static final int DEFAULT_MAX_TOTAL  = -1;
259    
260        /**
261         * The default "when exhausted action" for the pool.
262         * @see #WHEN_EXHAUSTED_BLOCK
263         * @see #WHEN_EXHAUSTED_FAIL
264         * @see #WHEN_EXHAUSTED_GROW
265         * @see #setWhenExhaustedAction
266         */
267        public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
268    
269        /**
270         * The default maximum amount of time (in milliseconds) the
271         * {@link #borrowObject} method should block before throwing
272         * an exception when the pool is exhausted and the
273         * {@link #getWhenExhaustedAction "when exhausted" action} is
274         * {@link #WHEN_EXHAUSTED_BLOCK}.
275         * @see #getMaxWait
276         * @see #setMaxWait
277         */
278        public static final long DEFAULT_MAX_WAIT = -1L;
279    
280        /**
281         * The default "test on borrow" value.
282         * @see #getTestOnBorrow
283         * @see #setTestOnBorrow
284         */
285        public static final boolean DEFAULT_TEST_ON_BORROW = false;
286    
287        /**
288         * The default "test on return" value.
289         * @see #getTestOnReturn
290         * @see #setTestOnReturn
291         */
292        public static final boolean DEFAULT_TEST_ON_RETURN = false;
293    
294        /**
295         * The default "test while idle" value.
296         * @see #getTestWhileIdle
297         * @see #setTestWhileIdle
298         * @see #getTimeBetweenEvictionRunsMillis
299         * @see #setTimeBetweenEvictionRunsMillis
300         */
301        public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
302    
303        /**
304         * The default "time between eviction runs" value.
305         * @see #getTimeBetweenEvictionRunsMillis
306         * @see #setTimeBetweenEvictionRunsMillis
307         */
308        public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
309    
310        /**
311         * The default number of objects to examine per run in the
312         * idle object evictor.
313         * @see #getNumTestsPerEvictionRun
314         * @see #setNumTestsPerEvictionRun
315         * @see #getTimeBetweenEvictionRunsMillis
316         * @see #setTimeBetweenEvictionRunsMillis
317         */
318        public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
319    
320        /**
321         * The default value for {@link #getMinEvictableIdleTimeMillis}.
322         * @see #getMinEvictableIdleTimeMillis
323         * @see #setMinEvictableIdleTimeMillis
324         */
325        public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
326    
327        /**
328         * The default minimum level of idle objects in the pool.
329         * @since Pool 1.3
330         * @see #setMinIdle
331         * @see #getMinIdle
332         */
333        public static final int DEFAULT_MIN_IDLE = 0;
334        
335        /**
336         * The default LIFO status. True means that borrowObject returns the
337         * most recently used ("last in") idle object in a pool (if there are
338         * idle instances available).  False means that pools behave as FIFO
339         * queues - objects are taken from idle object pools in the order that
340         * they are returned.
341         * @see #setLifo
342         */
343        public static final boolean DEFAULT_LIFO = true;
344        
345        //--- constructors -----------------------------------------------
346    
347        /**
348         * Create a new <code>GenericKeyedObjectPool</code> with no factory.
349         *
350         * @see #GenericKeyedObjectPool(KeyedPoolableObjectFactory)
351         * @see #setFactory(KeyedPoolableObjectFactory)
352         */
353        public TapestryKeyedObjectPool() {
354            this(null,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);
355        }
356    
357        /**
358         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
359         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
360         */
361        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory) {
362            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);
363        }
364    
365        /**
366         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
367         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
368         * @param config a non-<code>null</code> {@link GenericKeyedObjectPool.Config} describing the configuration
369         */
370        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
371            this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal, config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle,config.lifo);
372        }
373    
374        /**
375         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
376         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
377         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
378         */
379        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
380            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);
381        }
382    
383        /**
384         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
385         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
386         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
387         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
388         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
389         */
390        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
391            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);
392        }
393    
394        /**
395         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
396         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
397         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
398         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
399         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
400         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
401         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
402         */
403        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
404            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);
405        }
406    
407        /**
408         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
409         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
410         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
411         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
412         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
413         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
414         */
415        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
416            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);
417        }
418    
419        /**
420         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
421         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
422         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
423         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
424         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
425         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
426         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
427         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
428         */
429        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
430            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);
431        }
432    
433        /**
434         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
435         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
436         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
437         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
438         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
439         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
440         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
441         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
442         * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
443         * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
444         * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
445         * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
446         */
447        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
448            this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
449        }
450    
451        /**
452         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
453         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
454         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
455         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
456         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
457         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
458         * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
459         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
460         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
461         * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
462         * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
463         * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
464         * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
465         */
466        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
467            this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
468        }
469        
470        /**
471         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
472         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
473         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
474         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
475         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
476         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
477         * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
478         * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
479         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
480         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
481         * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
482         * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
483         * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
484         * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
485         * @since Pool 1.3
486         */
487        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
488            this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_LIFO);
489        }
490        
491        /**
492         * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
493         * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
494         * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
495         * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
496         * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
497         * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
498         * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
499         * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
500         * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
501         * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
502         * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
503         * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
504         * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
505         * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
506         * @param lifo whether or not the pools behave as LIFO (last in first out) queues (see {@link #setLifo}) 
507         * @since Pool 1.4
508         */
509        public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, boolean lifo) {
510            _factory = factory;
511            _maxActive = maxActive;
512            _lifo = lifo;
513            switch(whenExhaustedAction) {
514                case WHEN_EXHAUSTED_BLOCK:
515                case WHEN_EXHAUSTED_FAIL:
516                case WHEN_EXHAUSTED_GROW:
517                    _whenExhaustedAction = whenExhaustedAction;
518                    break;
519                default:
520                    throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
521            }
522            _maxWait = maxWait;
523            _maxIdle = maxIdle;
524            _maxTotal = maxTotal;
525            _minIdle = minIdle;
526            _testOnBorrow = testOnBorrow;
527            _testOnReturn = testOnReturn;
528            _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
529            _numTestsPerEvictionRun = numTestsPerEvictionRun;
530            _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
531            _testWhileIdle = testWhileIdle;
532    
533            _poolMap = new HashMap();
534            _poolList = new CursorableLinkedList();
535    
536            startEvictor(_timeBetweenEvictionRunsMillis);
537        }
538    
539        //--- public methods ---------------------------------------------
540    
541        //--- configuration methods --------------------------------------
542    
543        /**
544         * Returns the cap on the number of active instances per key.
545         * A negative value indicates no limit.
546         * @return the cap on the number of active instances per key.
547         * @see #setMaxActive
548         */
549        public synchronized int getMaxActive() {
550            return _maxActive;
551        }
552    
553        /**
554         * Sets the cap on the number of active instances per key.
555         * @param maxActive The cap on the number of active instances per key.
556         * Use a negative value for no limit.
557         * @see #getMaxActive
558         */
559        public synchronized void setMaxActive(int maxActive) {
560            _maxActive = maxActive;
561            notifyAll();
562        }
563    
564        /**
565         * Returns the overall maximum number of objects (across pools) that can
566         * exist at one time. A negative value indicates no limit.
567         * @return the maximum number of instances in circulation at one time.
568         * @see #setMaxTotal
569         */
570        public synchronized int getMaxTotal() {
571            return _maxTotal;
572        }
573    
574        /**
575         * Sets the cap on the total number of instances from all pools combined.
576         * When <code>maxTotal</code> is set to a
577         * positive value and {@link #borrowObject borrowObject} is invoked
578         * when at the limit with no idle instances available, an attempt is made to
579         * create room by clearing the oldest 15% of the elements from the keyed
580         * pools.
581         * 
582         * @param maxTotal The cap on the total number of instances across pools.
583         * Use a negative value for no limit.
584         * @see #getMaxTotal
585         */
586        public synchronized void setMaxTotal(int maxTotal) {
587            _maxTotal = maxTotal;
588            notifyAll();
589        }
590    
591        /**
592         * Returns the action to take when the {@link #borrowObject} method
593         * is invoked when the pool is exhausted (the maximum number
594         * of "active" objects has been reached).
595         *
596         * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, 
597         * {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
598         * @see #setWhenExhaustedAction
599         */
600        public synchronized byte getWhenExhaustedAction() {
601            return _whenExhaustedAction;
602        }
603    
604        /**
605         * Sets the action to take when the {@link #borrowObject} method
606         * is invoked when the pool is exhausted (the maximum number
607         * of "active" objects has been reached).
608         *
609         * @param whenExhaustedAction the action code, which must be one of
610         *        {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
611         *        or {@link #WHEN_EXHAUSTED_GROW}
612         * @see #getWhenExhaustedAction
613         */
614        public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
615            switch(whenExhaustedAction) {
616                case WHEN_EXHAUSTED_BLOCK:
617                case WHEN_EXHAUSTED_FAIL:
618                case WHEN_EXHAUSTED_GROW:
619                    _whenExhaustedAction = whenExhaustedAction;
620                    notifyAll();
621                    break;
622                default:
623                    throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
624            }
625        }
626    
627    
628        /**
629         * Returns the maximum amount of time (in milliseconds) the
630         * {@link #borrowObject} method should block before throwing
631         * an exception when the pool is exhausted and the
632         * {@link #setWhenExhaustedAction "when exhausted" action} is
633         * {@link #WHEN_EXHAUSTED_BLOCK}.
634         *
635         * When less than or equal to 0, the {@link #borrowObject} method
636         * may block indefinitely.
637         *
638         * @return the maximum number of milliseconds borrowObject will block.
639         * @see #setMaxWait
640         * @see #setWhenExhaustedAction
641         * @see #WHEN_EXHAUSTED_BLOCK
642         */
643        public synchronized long getMaxWait() {
644            return _maxWait;
645        }
646    
647        /**
648         * Sets the maximum amount of time (in milliseconds) the
649         * {@link #borrowObject} method should block before throwing
650         * an exception when the pool is exhausted and the
651         * {@link #setWhenExhaustedAction "when exhausted" action} is
652         * {@link #WHEN_EXHAUSTED_BLOCK}.
653         *
654         * When less than or equal to 0, the {@link #borrowObject} method
655         * may block indefinitely.
656         *
657         * @param maxWait the maximum number of milliseconds borrowObject will block or negative for indefinitely.
658         * @see #getMaxWait
659         * @see #setWhenExhaustedAction
660         * @see #WHEN_EXHAUSTED_BLOCK
661         */
662        public synchronized void setMaxWait(long maxWait) {
663            _maxWait = maxWait;
664        }
665    
666        /**
667         * Returns the cap on the number of "idle" instances per key.
668         * @return the maximum number of "idle" instances that can be held
669         * in a given keyed pool.
670         * @see #setMaxIdle
671         */
672        public synchronized int getMaxIdle() {
673            return _maxIdle;
674        }
675    
676        /**
677         * Sets the cap on the number of "idle" instances in the pool.
678         * @param maxIdle the maximum number of "idle" instances that can be held
679         * in a given keyed pool. Use a negative value for no limit.
680         * @see #getMaxIdle
681         * @see #DEFAULT_MAX_IDLE
682         */
683        public synchronized void setMaxIdle(int maxIdle) {
684            _maxIdle = maxIdle;
685            notifyAll();
686        }
687    
688        /**
689         * Sets the minimum number of idle objects to maintain in each of the keyed
690         * pools. This setting has no effect unless 
691         * <code>timeBetweenEvictionRunsMillis > 0</code> and attempts to ensure
692         * that each pool has the required minimum number of instances are only
693         * made during idle object eviction runs.
694         * @param poolSize - The minimum size of the each keyed pool
695         * @since Pool 1.3
696         * @see #getMinIdle
697         * @see #setTimeBetweenEvictionRunsMillis
698         */
699        public synchronized void setMinIdle(int poolSize) {
700            _minIdle = poolSize;
701        }
702    
703        /**
704         * Returns the minimum number of idle objects to maintain in each of the keyed
705         * pools. This setting has no effect unless 
706         * <code>timeBetweenEvictionRunsMillis > 0</code> and attempts to ensure
707         * that each pool has the required minimum number of instances are only
708         * made during idle object eviction runs.
709         * @return minimum size of the each keyed pool
710         * @since Pool 1.3
711         * @see #setTimeBetweenEvictionRunsMillis
712         */
713        public synchronized int getMinIdle() {
714            return _minIdle;
715        }
716    
717        /**
718         * When <code>true</code>, objects will be
719         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
720         * before being returned by the {@link #borrowObject}
721         * method.  If the object fails to validate,
722         * it will be dropped from the pool, and we will attempt
723         * to borrow another.
724         *
725         * @return <code>true</code> if objects are validated before being borrowed.
726         * @see #setTestOnBorrow
727         */
728        public boolean getTestOnBorrow() {
729            return _testOnBorrow;
730        }
731    
732        /**
733         * When <code>true</code>, objects will be
734         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
735         * before being returned by the {@link #borrowObject}
736         * method.  If the object fails to validate,
737         * it will be dropped from the pool, and we will attempt
738         * to borrow another.
739         *
740         * @param testOnBorrow whether object should be validated before being returned by borrowObject.
741         * @see #getTestOnBorrow
742         */
743        public void setTestOnBorrow(boolean testOnBorrow) {
744            _testOnBorrow = testOnBorrow;
745        }
746    
747        /**
748         * When <code>true</code>, objects will be
749         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
750         * before being returned to the pool within the
751         * {@link #returnObject}.
752         *
753         * @return <code>true</code> when objects will be validated before being returned.
754         * @see #setTestOnReturn
755         */
756        public boolean getTestOnReturn() {
757            return _testOnReturn;
758        }
759    
760        /**
761         * When <code>true</code>, objects will be
762         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
763         * before being returned to the pool within the
764         * {@link #returnObject}.
765         *
766         * @param testOnReturn <code>true</code> so objects will be validated before being returned.
767         * @see #getTestOnReturn
768         */
769        public void setTestOnReturn(boolean testOnReturn) {
770            _testOnReturn = testOnReturn;
771        }
772    
773        /**
774         * Returns the number of milliseconds to sleep between runs of the
775         * idle object evictor thread.
776         * When non-positive, no idle object evictor thread will be
777         * run.
778         *
779         * @return milliseconds to sleep between evictor runs.
780         * @see #setTimeBetweenEvictionRunsMillis
781         */
782        public synchronized long getTimeBetweenEvictionRunsMillis() {
783            return _timeBetweenEvictionRunsMillis;
784        }
785    
786        /**
787         * Sets the number of milliseconds to sleep between runs of the
788         * idle object evictor thread.
789         * When non-positive, no idle object evictor thread will be
790         * run.
791         *
792         * @param timeBetweenEvictionRunsMillis milliseconds to sleep between evictor runs.
793         * @see #getTimeBetweenEvictionRunsMillis
794         */
795        public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
796            _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
797            startEvictor(_timeBetweenEvictionRunsMillis);
798        }
799    
800        /**
801         * Returns the number of objects to examine during each run of the
802         * idle object evictor thread (if any).
803         *
804         * @return number of objects to examine each eviction run.
805         * @see #setNumTestsPerEvictionRun
806         * @see #setTimeBetweenEvictionRunsMillis
807         */
808        public synchronized int getNumTestsPerEvictionRun() {
809            return _numTestsPerEvictionRun;
810        }
811    
812        /**
813         * Sets the number of objects to examine during each run of the
814         * idle object evictor thread (if any).
815         * <p>
816         * When a negative value is supplied, <code>ceil({@link #getNumIdle()})/abs({@link #getNumTestsPerEvictionRun})</code>
817         * tests will be run.  I.e., when the value is <code>-n</code>, roughly one <code>n</code>th of the
818         * idle objects will be tested per run.
819         *
820         * @param numTestsPerEvictionRun number of objects to examine each eviction run.
821         * @see #getNumTestsPerEvictionRun
822         * @see #setTimeBetweenEvictionRunsMillis
823         */
824        public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
825            _numTestsPerEvictionRun = numTestsPerEvictionRun;
826        }
827    
828        /**
829         * Returns the minimum amount of time an object may sit idle in the pool
830         * before it is eligible for eviction by the idle object evictor
831         * (if any).
832         *
833         * @return minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
834         * @see #setMinEvictableIdleTimeMillis
835         * @see #setTimeBetweenEvictionRunsMillis
836         */
837        public synchronized long getMinEvictableIdleTimeMillis() {
838            return _minEvictableIdleTimeMillis;
839        }
840    
841        /**
842         * Sets the minimum amount of time an object may sit idle in the pool
843         * before it is eligible for eviction by the idle object evictor
844         * (if any).
845         * When non-positive, no objects will be evicted from the pool
846         * due to idle time alone.
847         *
848         * @param minEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
849         * @see #getMinEvictableIdleTimeMillis
850         * @see #setTimeBetweenEvictionRunsMillis
851         */
852        public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
853            _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
854        }
855    
856        /**
857         * When <code>true</code>, objects will be
858         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
859         * by the idle object evictor (if any).  If an object
860         * fails to validate, it will be dropped from the pool.
861         *
862         * @return <code>true</code> when objects are validated when borrowed.
863         * @see #setTestWhileIdle
864         * @see #setTimeBetweenEvictionRunsMillis
865         */
866        public synchronized boolean getTestWhileIdle() {
867            return _testWhileIdle;
868        }
869    
870        /**
871         * When <code>true</code>, objects will be
872         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
873         * by the idle object evictor (if any).  If an object
874         * fails to validate, it will be dropped from the pool.
875         *
876         * @param testWhileIdle <code>true</code> so objects are validated when borrowed.
877         * @see #getTestWhileIdle
878         * @see #setTimeBetweenEvictionRunsMillis
879         */
880        public synchronized void setTestWhileIdle(boolean testWhileIdle) {
881            _testWhileIdle = testWhileIdle;
882        }
883    
884        /**
885         * Sets the configuration.
886         * @param conf the new configuration to use.
887         * @see GenericKeyedObjectPool.Config
888         */
889        public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
890            setMaxIdle(conf.maxIdle);
891            setMaxActive(conf.maxActive);
892            setMaxTotal(conf.maxTotal);
893            setMinIdle(conf.minIdle);
894            setMaxWait(conf.maxWait);
895            setWhenExhaustedAction(conf.whenExhaustedAction);
896            setTestOnBorrow(conf.testOnBorrow);
897            setTestOnReturn(conf.testOnReturn);
898            setTestWhileIdle(conf.testWhileIdle);
899            setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
900            setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
901            setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
902        }
903        
904        /**
905         * Whether or not the idle object pools act as LIFO queues. True means
906         * that borrowObject returns the most recently used ("last in") idle object
907         * in a pool (if there are idle instances available).  False means that
908         * the pools behave as FIFO queues - objects are taken from idle object
909         * pools in the order that they are returned.
910         * 
911         * @return <code>true</code> if the pools are configured to act as LIFO queues
912         * @since 1.4
913         */
914         public synchronized boolean getLifo() {
915             return _lifo;
916         }
917    
918         /**
919          * Sets the LIFO property of the pools. True means that borrowObject returns
920          * the most recently used ("last in") idle object in a pool (if there are
921          * idle instances available).  False means that the pools behave as FIFO
922          * queues - objects are taken from idle object pools in the order that
923          * they are returned.
924          * 
925          * @param lifo the new value for the lifo property
926          * @since 1.4
927          */
928         public synchronized void setLifo(boolean lifo) {
929             this._lifo = lifo;
930         }
931    
932        //-- ObjectPool methods ------------------------------------------
933    
934        public Object borrowObject(Object key) throws Exception {
935            long starttime = System.currentTimeMillis();
936            boolean newlyCreated = false;
937            for(;;) {
938                ObjectTimestampPair pair = null;
939                ObjectQueue pool = null;
940                synchronized (_poolMap) {
941                    assertOpen();
942                    pool = (ObjectQueue)(_poolMap.get(key));
943                    if(null == pool) {
944                        pool = new ObjectQueue();
945                        _poolMap.put(key,pool);
946                        _poolList.add(key);
947                    }
948                }
949                    // if there are any sleeping, just grab one of those
950                    try {
951                            synchronized (pool) {
952                                    pair = (ObjectTimestampPair)(pool.queue.removeFirst());
953                            }
954                        if(null != pair) {
955                            _totalIdle--;
956                        }
957                    } catch(NoSuchElementException e) { /* ignored */
958                    }
959                    // otherwise
960                    if(null == pair) {
961                        // if there is a totalMaxActive and we are at the limit then
962                        // we have to make room
963                        if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
964                            clearOldest();
965                        }
966        
967                        // check if we can create one
968                        // (note we know that the num sleeping is 0, else we wouldn't be here)
969                        if ((_maxActive < 0 || pool.activeCount < _maxActive) &&
970                            (_maxTotal < 0 || _totalActive + _totalIdle < _maxTotal)) {
971                            Object obj = _factory.makeObject(key);
972                            pair = new ObjectTimestampPair(obj);
973                            newlyCreated = true;
974                        } else {
975                            // the pool is exhausted
976                            switch(_whenExhaustedAction) {
977                                case WHEN_EXHAUSTED_GROW:
978                                    Object obj = _factory.makeObject(key);
979                                    pair = new ObjectTimestampPair(obj);
980                                    break;
981                                case WHEN_EXHAUSTED_FAIL:
982                                    throw new NoSuchElementException();
983                                case WHEN_EXHAUSTED_BLOCK:
984                                    try {
985                                        if(_maxWait <= 0) {
986                                            wait();
987                                        } else {
988                                            // this code may be executed again after a notify then continue cycle
989                                            // so, need to calculate the amount of time to wait
990                                            final long elapsed = (System.currentTimeMillis() - starttime);
991                                            final long waitTime = _maxWait - elapsed;
992                                            if (waitTime > 0)
993                                            {
994                                                wait(waitTime);
995                                            }
996                                        }
997                                    } catch(InterruptedException e) {
998                                        // ignored
999                                    }
1000                                    if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
1001                                        throw new NoSuchElementException("Timeout waiting for idle object");
1002                                    } else {
1003                                        continue; // keep looping
1004                                    }
1005                                default:
1006                                    throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
1007                            }
1008                        }
1009                    
1010                    pool.incrementActiveCount();
1011                }
1012                
1013                // Activate.  If activate fails, decrement active count and destroy.
1014                // If instance failing activation is new, throw NoSuchElementException;
1015                // otherwise keep looping
1016                try {
1017                    _factory.activateObject(key, pair.value);
1018                } catch (Exception e) {
1019                    try {
1020                        _factory.destroyObject(key,pair.value);
1021                        synchronized (this) {
1022                            pool.decrementActiveCount();
1023                        }
1024                    } catch (Exception e2) {
1025                        // swallowed
1026                    }
1027                    if(newlyCreated) {
1028                        throw new NoSuchElementException(
1029                           "Could not create a validated object, cause: "
1030                                + e.getMessage());
1031                    }
1032                    else {
1033                        continue; // keep looping
1034                    }
1035                }
1036    
1037                // Validate.  If validation fails, decrement active count and
1038                // destroy. If instance failing validation is new, throw
1039                // NoSuchElementException; otherwise keep looping
1040                boolean invalid = true;
1041                try {
1042                    invalid = _testOnBorrow && !_factory.validateObject(key, pair.value);
1043                } catch (Exception e) {
1044                    // swallowed
1045                }
1046                if (invalid) {
1047                    try {
1048                        _factory.destroyObject(key,pair.value);
1049                        synchronized (pool) {
1050                            pool.decrementActiveCount();
1051                        }
1052                    } catch (Exception e) {
1053                        // swallowed
1054                    }
1055                    if(newlyCreated) {
1056                        throw new NoSuchElementException("Could not create a validated object");
1057                    } // else keep looping
1058                } else {
1059                    return pair.value;
1060                }
1061            }
1062        }
1063    
1064        /**
1065         * Clears the pool, removing all pooled instances.
1066         */
1067        public synchronized void clear() {
1068            for(Iterator entries = _poolMap.entrySet().iterator(); entries.hasNext(); ) {
1069                final Map.Entry entry = (Map.Entry)entries.next();
1070                final Object key = entry.getKey();
1071                final CursorableLinkedList list = ((ObjectQueue)(entry.getValue())).queue;
1072                for(Iterator it = list.iterator(); it.hasNext(); ) {
1073                    try {
1074                        _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
1075                    } catch(Exception e) {
1076                        // ignore error, keep destroying the rest
1077                    }
1078                    it.remove();
1079                }
1080            }
1081            _poolMap.clear();
1082            _poolList.clear();
1083            _totalIdle = 0;
1084            notifyAll();
1085        }
1086    
1087        /**
1088         * Method clears oldest 15% of objects in pool.  The method sorts the
1089         * objects into a TreeMap and then iterates the first 15% for removal
1090         * @since Pool 1.3
1091         */
1092        public synchronized void clearOldest() {
1093            // build sorted map of idle objects
1094            final Map map = new TreeMap();
1095            for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) {
1096                final Object key = keyiter.next();
1097                final CursorableLinkedList list = ((ObjectQueue)_poolMap.get(key)).queue;
1098                for (Iterator it = list.iterator(); it.hasNext();) {
1099                    // each item into the map uses the objectimestamppair object
1100                    // as the key.  It then gets sorted based on the timstamp field
1101                    // each value in the map is the parent list it belongs in.
1102                    map.put(it.next(), key);
1103                }
1104            }
1105    
1106            // Now iterate created map and kill the first 15% plus one to account for zero
1107            Set setPairKeys = map.entrySet();
1108            int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
1109    
1110            Iterator iter = setPairKeys.iterator();
1111            while (iter.hasNext() && itemsToRemove > 0) {
1112                Map.Entry entry = (Map.Entry) iter.next();
1113                // kind of backwards on naming.  In the map, each key is the objecttimestamppair
1114                // because it has the ordering with the timestamp value.  Each value that the
1115                // key references is the key of the list it belongs to.
1116                Object key = entry.getValue();
1117                ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey();
1118                final CursorableLinkedList list = 
1119                    ((ObjectQueue)(_poolMap.get(key))).queue;
1120                list.remove(pairTimeStamp);
1121    
1122                try {
1123                    _factory.destroyObject(key, pairTimeStamp.value);
1124                } catch (Exception e) {
1125                    // ignore error, keep destroying the rest
1126                }
1127                // if that was the last object for that key, drop that pool
1128                if (list.isEmpty()) {
1129                    _poolMap.remove(key);
1130                    _poolList.remove(key);
1131                }
1132                _totalIdle--;
1133                itemsToRemove--;
1134            }
1135            notifyAll();
1136        }
1137    
1138        /**
1139         * Clears the specified pool, removing all pooled instances corresponding to the given <code>key</code>.
1140         *
1141         * @param key the key to clear
1142         */
1143        public synchronized void clear(Object key) {
1144            final ObjectQueue pool = (ObjectQueue)(_poolMap.remove(key));
1145            if(null == pool) {
1146                return;
1147            } else {
1148                _poolList.remove(key);
1149                for(Iterator it = pool.queue.iterator(); it.hasNext(); ) {
1150                    try {
1151                        _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
1152                    } catch(Exception e) {
1153                        // ignore error, keep destroying the rest
1154                    }
1155                    it.remove();
1156                    _totalIdle--;
1157                }
1158            }
1159            
1160            notifyAll();
1161        }
1162    
1163        /**
1164         * Returns the total number of instances current borrowed from this pool but not yet returned.
1165         *
1166         * @return the total number of instances currently borrowed from this pool
1167         */
1168        public synchronized int getNumActive() {
1169            return _totalActive;
1170        }
1171    
1172        /**
1173         * Returns the total number of instances currently idle in this pool.
1174         *
1175         * @return the total number of instances currently idle in this pool
1176         */
1177        public synchronized int getNumIdle() {
1178            return _totalIdle;
1179        }
1180    
1181        /**
1182         * Returns the number of instances currently borrowed from but not yet returned
1183         * to the pool corresponding to the given <code>key</code>.
1184         *
1185         * @param key the key to query
1186         * @return the number of instances corresponding to the given <code>key</code> currently borrowed in this pool
1187         */
1188        public synchronized int getNumActive(Object key) {
1189            final ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
1190            return pool != null ? pool.activeCount : 0;
1191        }
1192    
1193        /**
1194         * Returns the number of instances corresponding to the given <code>key</code> currently idle in this pool.
1195         *
1196         * @param key the key to query
1197         * @return the number of instances corresponding to the given <code>key</code> currently idle in this pool
1198         */
1199        public synchronized int getNumIdle(Object key) {
1200            final ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
1201            return pool != null ? pool.queue.size() : 0;
1202        }
1203    
1204        public void returnObject(Object key, Object obj) throws Exception {
1205            try {
1206                addObjectToPool(key, obj, true);
1207            } catch (Exception e) {
1208                if (_factory != null) {
1209                    try {
1210                        _factory.destroyObject(key, obj);
1211                    } catch (Exception e2) {
1212                        // swallowed
1213                    }
1214                    // TODO: Correctness here depends on control in addObjectToPool.
1215                    // These two methods should be refactored, removing the 
1216                    // "behavior flag",decrementNumActive, from addObjectToPool.
1217                    ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
1218                    if (pool != null) {
1219                        synchronized(pool) {
1220                            pool.decrementActiveCount();
1221                            notifyAll();
1222                        }  
1223                    }
1224                }
1225            }
1226        }
1227    
1228        private void addObjectToPool(Object key, Object obj,
1229                boolean decrementNumActive) throws Exception {
1230    
1231            // if we need to validate this object, do so
1232            boolean success = true; // whether or not this object passed validation
1233            if(_testOnReturn && !_factory.validateObject(key, obj)) {
1234                success = false;
1235            } else {
1236                _factory.passivateObject(key, obj);
1237            }
1238    
1239            boolean shouldDestroy = !success;
1240            ObjectQueue pool;
1241            
1242            // Add instance to pool if there is room and it has passed validation
1243            // (if testOnreturn is set)
1244            synchronized (this) {
1245                // grab the pool (list) of objects associated with the given key
1246                pool = (ObjectQueue) (_poolMap.get(key));
1247                // if it doesn't exist, create it
1248                if(null == pool) {
1249                    pool = new ObjectQueue();
1250                    _poolMap.put(key, pool);
1251                    _poolList.add(key);
1252                }
1253            }
1254            synchronized (pool) {
1255                if (isClosed()) {
1256                    shouldDestroy = true;
1257                } else {
1258                    // if there's no space in the pool, flag the object for destruction
1259                    // else if we passivated successfully, return it to the pool
1260                    if(_maxIdle >= 0 && (pool.queue.size() >= _maxIdle)) {
1261                        shouldDestroy = true;
1262                    } else if(success) {
1263                        // borrowObject always takes the first element from the queue,
1264                        // so for LIFO, push on top, FIFO add to end
1265                        if (_lifo) {
1266                            pool.queue.addFirst(new ObjectTimestampPair(obj)); 
1267                        } else {
1268                            pool.queue.addLast(new ObjectTimestampPair(obj));
1269                        }
1270                        _totalIdle++;
1271                    }
1272                }
1273            }
1274    
1275            // Destroy the instance if necessary 
1276            if(shouldDestroy) {
1277                try {
1278                    _factory.destroyObject(key, obj);
1279                } catch(Exception e) {
1280                    // ignored?
1281                }
1282            }
1283            
1284            // Decrement active count *after* destroy if applicable
1285            if (decrementNumActive) {
1286                synchronized(this) {
1287                    pool.decrementActiveCount();
1288                    notifyAll();
1289                }
1290            }
1291        }
1292    
1293        public void invalidateObject(Object key, Object obj) throws Exception {
1294            try {
1295                _factory.destroyObject(key, obj);
1296            } finally {
1297                synchronized (this) {
1298                    ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
1299                    if(null == pool) {
1300                        pool = new ObjectQueue();
1301                        _poolMap.put(key, pool);
1302                        _poolList.add(key);
1303                    }
1304                    pool.decrementActiveCount();
1305                    notifyAll(); // _totalActive has changed
1306                }
1307            }
1308        }
1309    
1310        /**
1311         * Create an object using the {@link KeyedPoolableObjectFactory#makeObject factory},
1312         * passivate it, and then place it in the idle object pool.
1313         * <code>addObject</code> is useful for "pre-loading" a pool with idle objects.
1314         *
1315         * @param key the key a new instance should be added to
1316         * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject} fails.
1317         * @throws IllegalStateException when no {@link #setFactory factory} has been set or after {@link #close} has been called on this pool.
1318         */
1319        public void addObject(Object key) throws Exception {
1320            assertOpen();
1321            if (_factory == null) {
1322                throw new IllegalStateException("Cannot add objects without a factory.");
1323            }
1324            Object obj = _factory.makeObject(key);
1325            synchronized (this) {
1326                try {
1327                    assertOpen();
1328                    addObjectToPool(key, obj, false);
1329                } catch (IllegalStateException ex) { // Pool closed
1330                    try {
1331                        _factory.destroyObject(key, obj);
1332                    } catch (Exception ex2) {
1333                        // swallow
1334                    }
1335                    throw ex;
1336                }
1337            }
1338        }
1339    
1340        /**
1341         * Registers a key for pool control.
1342         *
1343         * If <code>populateImmediately</code> is <code>true</code> and
1344         * <code>minIdle > 0,</code> the pool under the given key will be
1345         * populated immediately with <code>minIdle</code> idle instances.
1346         *
1347         * @param key - The key to register for pool control.
1348         * @param populateImmediately - If this is <code>true</code>, the pool
1349         * will be populated immediately.
1350         * @since Pool 1.3
1351         */
1352        public synchronized void preparePool(Object key, boolean populateImmediately) {
1353            ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
1354            if (null == pool) {
1355                pool = new ObjectQueue();
1356                _poolMap.put(key,pool);
1357                _poolList.add(key);
1358            }
1359    
1360            if (populateImmediately) {
1361                try {
1362                    // Create the pooled objects
1363                    ensureMinIdle(key);
1364                }
1365                catch (Exception e) {
1366                    //Do nothing
1367                }
1368            }
1369        }
1370    
1371        public void close() throws Exception {
1372            super.close();
1373            synchronized (this) {
1374                clear();
1375                if(null != _evictionCursor) {
1376                    _evictionCursor.close();
1377                    _evictionCursor = null;
1378                }
1379                if(null != _evictionKeyCursor) {
1380                    _evictionKeyCursor.close();
1381                    _evictionKeyCursor = null;
1382                }
1383                startEvictor(-1L);
1384            }
1385        }
1386    
1387        public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
1388            assertOpen();
1389            if(0 < getNumActive()) {
1390                throw new IllegalStateException("Objects are already active");
1391            } else {
1392                clear();
1393                _factory = factory;
1394            }
1395        }
1396    
1397        /**
1398         * <p>Perform <code>numTests</code> idle object eviction tests, evicting
1399         * examined objects that meet the criteria for eviction. If 
1400         * <code>testWhileIdle</code> is true, examined objects are validated
1401         * when visited (and removed if invalid); otherwise only objects that
1402         * have been idle for more than <code>minEvicableIdletimeMillis</code>
1403         * are removed.</p>
1404         * 
1405         * <p>Successive activations of this method examine objects in keyed pools
1406         * in sequence, cycling through the keys and examining objects in
1407         * oldest-to-youngest order within the keyed pools.</p>
1408         *
1409         * @throws Exception when there is a problem evicting idle objects.
1410         */
1411        public synchronized void evict() throws Exception {
1412            // Initialize key to last key value
1413            Object key = null;
1414            if (_evictionKeyCursor != null && 
1415                    _evictionKeyCursor._lastReturned != null) {
1416                key = _evictionKeyCursor._lastReturned.value();
1417            }
1418            
1419            for (int i=0,m=getNumTests(); i<m; i++) {
1420                // make sure pool map is not empty; otherwise do nothing
1421                if (_poolMap == null || _poolMap.size() == 0) {
1422                    continue;
1423                }
1424    
1425                // if we don't have a key cursor, then create one
1426                if (null == _evictionKeyCursor) {
1427                    resetEvictionKeyCursor();
1428                    key = null;
1429                }
1430    
1431                // if we don't have an object cursor, create one
1432                if (null == _evictionCursor) {
1433                    // if the _evictionKeyCursor has a next value, use this key
1434                    if (_evictionKeyCursor.hasNext()) {
1435                        key = _evictionKeyCursor.next();
1436                        resetEvictionObjectCursor(key);
1437                    } else {
1438                        // Reset the key cursor and try again
1439                        resetEvictionKeyCursor();
1440                        if (_evictionKeyCursor != null) {
1441                            if (_evictionKeyCursor.hasNext()) {
1442                                key = _evictionKeyCursor.next();
1443                                resetEvictionObjectCursor(key);
1444                            }
1445                        }
1446                    }
1447                }  
1448    
1449                if (_evictionCursor == null) {
1450                    continue; // should never happen; do nothing
1451                }
1452    
1453                // If eviction cursor is exhausted, try to move
1454                // to the next key and reset
1455                if((_lifo && !_evictionCursor.hasPrevious()) ||
1456                        (!_lifo && !_evictionCursor.hasNext())) {
1457                    if (_evictionKeyCursor != null) {
1458                        if (_evictionKeyCursor.hasNext()) {
1459                            key = _evictionKeyCursor.next();
1460                            resetEvictionObjectCursor(key);
1461                        } else { // Need to reset Key cursor
1462                            resetEvictionKeyCursor();
1463                            if (_evictionKeyCursor != null) {
1464                                if (_evictionKeyCursor.hasNext()) {
1465                                    key = _evictionKeyCursor.next();
1466                                    resetEvictionObjectCursor(key);
1467                                }
1468                            }
1469                        }
1470                    }
1471                }
1472    
1473                if((_lifo && !_evictionCursor.hasPrevious()) ||
1474                        (!_lifo && !_evictionCursor.hasNext())) {
1475                    continue; // reset failed, do nothing
1476                }
1477    
1478                // if LIFO and the _evictionCursor has a previous object, 
1479                // or FIFO and _evictionCursor has a next object, test it
1480                ObjectTimestampPair pair = _lifo ? 
1481                        (ObjectTimestampPair) _evictionCursor.previous() : 
1482                        (ObjectTimestampPair) _evictionCursor.next();
1483                boolean removeObject=false;
1484                if((_minEvictableIdleTimeMillis > 0) &&
1485                   (System.currentTimeMillis() - pair.tstamp > 
1486                   _minEvictableIdleTimeMillis)) {
1487                    removeObject=true;
1488                }
1489                if(_testWhileIdle && removeObject == false) {
1490                    boolean active = false;
1491                    try {
1492                        _factory.activateObject(key,pair.value);
1493                        active = true;
1494                    } catch(Exception e) {
1495                        removeObject=true;
1496                    }
1497                    if(active) {
1498                        if(!_factory.validateObject(key,pair.value)) {
1499                            removeObject=true;
1500                        } else {
1501                            try {
1502                                _factory.passivateObject(key,pair.value);
1503                            } catch(Exception e) {
1504                                removeObject=true;
1505                            }
1506                        }
1507                    }
1508                }
1509                if(removeObject) {
1510                    try {
1511                        _evictionCursor.remove();
1512                        _totalIdle--;
1513                        _factory.destroyObject(key, pair.value);
1514                        // Do not remove the key from the _poolList or _poolmap,
1515                        // even if the list stored in the _poolMap for this key is
1516                        // empty when minIdle > 0.
1517                        //
1518                        // Otherwise if it was the last object for that key,
1519                        // drop that pool
1520                        if (_minIdle == 0) {
1521                            ObjectQueue objectQueue = 
1522                                (ObjectQueue)_poolMap.get(key);
1523                            if (objectQueue != null && 
1524                                    objectQueue.queue.isEmpty()) {
1525                                _poolMap.remove(key);
1526                                _poolList.remove(key);  
1527                            }
1528                        }
1529                    } catch(Exception e) {
1530                        ; // ignored
1531                    }
1532                }
1533            }
1534        }
1535        
1536        /**
1537         * Resets the eviction key cursor and closes any
1538         * associated eviction object cursor
1539         */
1540        private void resetEvictionKeyCursor() {
1541            if (_evictionKeyCursor != null) {
1542                _evictionKeyCursor.close();
1543            }
1544            _evictionKeyCursor = _poolList.cursor();
1545            if (null != _evictionCursor) {
1546                _evictionCursor.close();
1547                _evictionCursor = null;
1548            }  
1549        }
1550        
1551        /**
1552         * Resets the eviction object cursor for the given key
1553         * 
1554         * @param key eviction key
1555         */
1556        private void resetEvictionObjectCursor(Object key) {
1557            if (_evictionCursor != null) {
1558                _evictionCursor.close();
1559            }
1560            if (_poolMap == null) { 
1561                return;
1562            }
1563            ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
1564            if (pool != null) {
1565                CursorableLinkedList queue = 
1566                    (CursorableLinkedList)(pool.queue);
1567                _evictionCursor = queue.cursor(_lifo ? queue.size() : 0);   
1568            }
1569        }
1570    
1571        /**
1572         * Iterates through all the known keys and creates any necessary objects to maintain
1573         * the minimum level of pooled objects.
1574         * @see #getMinIdle
1575         * @see #setMinIdle
1576         * @throws Exception If there was an error whilst creating the pooled objects.
1577         */
1578        private synchronized void ensureMinIdle() throws Exception {
1579            Iterator iterator = _poolMap.keySet().iterator();
1580    
1581            //Check if should sustain the pool
1582            if (_minIdle > 0) {
1583                // Loop through all elements in _poolList
1584                // Find out the total number of max active and max idle for that class
1585                // If the number is less than the minIdle, do creation loop to boost numbers
1586                // Increment idle count + 1
1587                while (iterator.hasNext()) {
1588                    //Get the next key to process
1589                    Object key = iterator.next();
1590                    ensureMinIdle(key);
1591                }
1592            }
1593        }
1594    
1595        /**
1596         * Re-creates any needed objects to maintain the minimum levels of
1597         * pooled objects for the specified key.
1598         *
1599         * This method uses {@link #calculateDefecit} to calculate the number
1600         * of objects to be created. {@link #calculateDefecit} can be overridden to
1601         * provide a different method of calculating the number of objects to be
1602         * created.
1603         * @param key The key to process
1604         * @throws Exception If there was an error whilst creating the pooled objects
1605         */
1606        private synchronized void ensureMinIdle(Object key) throws Exception {
1607            // Calculate current pool objects
1608            int numberToCreate = calculateDefecit(key);
1609    
1610            //Create required pool objects, if none to create, this loop will not be run.
1611            for (int i = 0; i < numberToCreate; i++) {
1612                addObject(key);
1613            }
1614        }
1615    
1616        //--- non-public methods ----------------------------------------
1617    
1618        /**
1619         * Start the eviction thread or service, or when
1620         * <code>delay</code> is non-positive, stop it
1621         * if it is already running.
1622         *
1623         * @param delay milliseconds between evictor runs.
1624         */
1625        protected synchronized void startEvictor(long delay) {
1626            if(null != _evictor) {
1627                EvictionTimer.cancel(_evictor);
1628                _evictor = null;
1629            }
1630            if(delay > 0) {
1631                _evictor = new Evictor();
1632                EvictionTimer.schedule(_evictor, delay, delay);
1633            }
1634        }
1635    
1636        synchronized String debugInfo() {
1637            StringBuffer buf = new StringBuffer();
1638            buf.append("Active: ").append(getNumActive()).append("\n");
1639            buf.append("Idle: ").append(getNumIdle()).append("\n");
1640            Iterator it = _poolMap.keySet().iterator();
1641            while(it.hasNext()) {
1642                buf.append("\t").append(_poolMap.get(it.next())).append("\n");
1643            }
1644            return buf.toString();
1645        }
1646    
1647        private int getNumTests() {
1648            if(_numTestsPerEvictionRun >= 0) {
1649                return _numTestsPerEvictionRun;
1650            } else {
1651                return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
1652            }
1653        }
1654    
1655        /**
1656         * This returns the number of objects to create during the pool
1657         * sustain cycle. This will ensure that the minimum number of idle
1658         * connections is maintained without going past the maxPool value.
1659         * <p>
1660         * This method has been left public so derived classes can override
1661         * the way the defecit is calculated. ie... Increase/decrease the pool
1662         * size at certain times of day to accomodate for usage patterns.
1663         *
1664         * @param key - The key of the pool to calculate the number of
1665         *              objects to be re-created
1666         * @return The number of objects to be created
1667         */
1668        private int calculateDefecit(Object key) {
1669            int objectDefecit = 0;
1670    
1671            //Calculate no of objects needed to be created, in order to have
1672            //the number of pooled objects < maxActive();
1673            objectDefecit = getMinIdle() - getNumIdle(key);
1674            if (getMaxActive() > 0) {
1675                int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
1676                objectDefecit = Math.min(objectDefecit, growLimit);
1677            }
1678    
1679            // Take the maxTotal limit into account
1680            if (getMaxTotal() > 0) {
1681                int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
1682                objectDefecit = Math.min(objectDefecit, growLimit);
1683            }
1684    
1685            return objectDefecit;
1686        }
1687    
1688        //--- inner classes ----------------------------------------------
1689    
1690        /**
1691         * A "struct" that keeps additional information about the actual queue of pooled objects.
1692         */
1693        private class ObjectQueue {
1694            private int activeCount = 0;
1695            private final CursorableLinkedList queue = new CursorableLinkedList();
1696    
1697            void incrementActiveCount() {
1698                _totalActive++;
1699                activeCount++;
1700            }
1701    
1702            void decrementActiveCount() {
1703                _totalActive--;
1704                if (activeCount > 0) {
1705                    activeCount--;
1706                }
1707            }
1708        }
1709        
1710        /**
1711         * A simple "struct" encapsulating an object instance and a timestamp.
1712         *
1713         * Implements Comparable, objects are sorted from old to new.
1714         *
1715         * This is also used by {@link GenericObjectPool}.
1716         */
1717        static class ObjectTimestampPair implements Comparable {
1718            Object value;
1719            long tstamp;
1720    
1721            ObjectTimestampPair(Object val) {
1722                this(val, System.currentTimeMillis());
1723            }
1724    
1725            ObjectTimestampPair(Object val, long time) {
1726                value = val;
1727                tstamp = time;
1728            }
1729    
1730            public String toString() {
1731                return value + ";" + tstamp;
1732            }
1733    
1734            public int compareTo(Object obj) {
1735                return compareTo((ObjectTimestampPair) obj);
1736            }
1737    
1738            public int compareTo(ObjectTimestampPair other) {
1739                final long tstampdiff = this.tstamp - other.tstamp;
1740                if (tstampdiff == 0) {
1741                    // make sure the natural ordering is consistent with equals
1742                    // see java.lang.Comparable Javadocs
1743                    return System.identityHashCode(this) - System.identityHashCode(other);
1744                } else {
1745                    // handle int overflow
1746                    return (int)Math.min(Math.max(tstampdiff, Integer.MIN_VALUE), Integer.MAX_VALUE);
1747                }
1748            }
1749        }
1750    
1751        /**
1752         * The idle object evictor {@link TimerTask}.
1753         * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1754         */
1755        private class Evictor extends TimerTask {
1756            public void run() {
1757                //Evict from the pool
1758                try {
1759                    evict();
1760                } catch(Exception e) {
1761                    // ignored
1762                }
1763                //Re-create the connections.
1764                try {
1765                    ensureMinIdle();
1766                } catch (Exception e) {
1767                    // ignored
1768                }
1769            }
1770        }
1771    
1772        /**
1773         * A simple "struct" encapsulating the
1774         * configuration information for a <code>GenericKeyedObjectPool</code>.
1775         * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
1776         * @see GenericKeyedObjectPool#setConfig
1777         */
1778        public static class Config {
1779            /**
1780             * @see GenericKeyedObjectPool#setMaxIdle
1781             */
1782            public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
1783            /**
1784             * @see GenericKeyedObjectPool#setMaxActive
1785             */
1786            public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
1787            /**
1788             * @see GenericKeyedObjectPool#setMaxTotal
1789             */
1790            public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
1791            /**
1792             * @see GenericKeyedObjectPool#setMinIdle
1793             */
1794            public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE;
1795            /**
1796             * @see GenericKeyedObjectPool#setMaxWait
1797             */
1798            public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
1799            /**
1800             * @see GenericKeyedObjectPool#setWhenExhaustedAction
1801             */
1802            public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
1803            /**
1804             * @see GenericKeyedObjectPool#setTestOnBorrow
1805             */
1806            public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
1807            /**
1808             * @see GenericKeyedObjectPool#setTestOnReturn
1809             */
1810            public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
1811            /**
1812             * @see GenericKeyedObjectPool#setTestWhileIdle
1813             */
1814            public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
1815            /**
1816             * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1817             */
1818            public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1819            /**
1820             * @see GenericKeyedObjectPool#setNumTestsPerEvictionRun
1821             */
1822            public int numTestsPerEvictionRun =  GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1823            /**
1824             * @see GenericKeyedObjectPool#setMinEvictableIdleTimeMillis
1825             */
1826            public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1827            /**
1828             * @see GenericKeyedObjectPool#setLifo
1829             */
1830            public boolean lifo = GenericKeyedObjectPool.DEFAULT_LIFO;
1831        }
1832    
1833        //--- protected attributes ---------------------------------------
1834    
1835        /**
1836         * The cap on the number of idle instances in the pool.
1837         * @see #setMaxIdle
1838         * @see #getMaxIdle
1839         */
1840        private int _maxIdle = DEFAULT_MAX_IDLE;
1841    
1842        /**
1843         * The minimum no of idle objects to keep in the pool.
1844         * @see #setMinIdle
1845         * @see #getMinIdle
1846         */
1847        private int _minIdle = DEFAULT_MIN_IDLE;
1848    
1849        /**
1850         * The cap on the number of active instances from the pool.
1851         * @see #setMaxActive
1852         * @see #getMaxActive
1853         */
1854        private int _maxActive = DEFAULT_MAX_ACTIVE;
1855    
1856        /**
1857         * The cap on the total number of instances from the pool if non-positive.
1858         * @see #setMaxTotal
1859         * @see #getMaxTotal
1860         */
1861        private int _maxTotal = DEFAULT_MAX_TOTAL;
1862        
1863        /**
1864         * The maximum amount of time (in millis) the
1865         * {@link #borrowObject} method should block before throwing
1866         * an exception when the pool is exhausted and the
1867         * {@link #getWhenExhaustedAction "when exhausted" action} is
1868         * {@link #WHEN_EXHAUSTED_BLOCK}.
1869         *
1870         * When less than or equal to 0, the {@link #borrowObject} method
1871         * may block indefinitely.
1872         *
1873         * @see #setMaxWait
1874         * @see #getMaxWait
1875         * @see #WHEN_EXHAUSTED_BLOCK
1876         * @see #setWhenExhaustedAction
1877         * @see #getWhenExhaustedAction
1878         */
1879        private long _maxWait = DEFAULT_MAX_WAIT;
1880    
1881        /**
1882         * The action to take when the {@link #borrowObject} method
1883         * is invoked when the pool is exhausted (the maximum number
1884         * of "active" objects has been reached).
1885         *
1886         * @see #WHEN_EXHAUSTED_BLOCK
1887         * @see #WHEN_EXHAUSTED_FAIL
1888         * @see #WHEN_EXHAUSTED_GROW
1889         * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
1890         * @see #setWhenExhaustedAction
1891         * @see #getWhenExhaustedAction
1892         */
1893        private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
1894    
1895        /**
1896         * When <code>true</code>, objects will be
1897         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1898         * before being returned by the {@link #borrowObject}
1899         * method.  If the object fails to validate,
1900         * it will be dropped from the pool, and we will attempt
1901         * to borrow another.
1902         *
1903         * @see #setTestOnBorrow
1904         * @see #getTestOnBorrow
1905         */
1906        private volatile boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
1907    
1908        /**
1909         * When <code>true</code>, objects will be
1910         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1911         * before being returned to the pool within the
1912         * {@link #returnObject}.
1913         *
1914         * @see #getTestOnReturn
1915         * @see #setTestOnReturn
1916         */
1917        private volatile boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
1918    
1919        /**
1920         * When <code>true</code>, objects will be
1921         * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1922         * by the idle object evictor (if any).  If an object
1923         * fails to validate, it will be dropped from the pool.
1924         *
1925         * @see #setTestWhileIdle
1926         * @see #getTestWhileIdle
1927         * @see #getTimeBetweenEvictionRunsMillis
1928         * @see #setTimeBetweenEvictionRunsMillis
1929         */
1930        private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
1931    
1932        /**
1933         * The number of milliseconds to sleep between runs of the
1934         * idle object evictor thread.
1935         * When non-positive, no idle object evictor thread will be
1936         * run.
1937         *
1938         * @see #setTimeBetweenEvictionRunsMillis
1939         * @see #getTimeBetweenEvictionRunsMillis
1940         */
1941        private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1942    
1943        /**
1944         * The number of objects to examine during each run of the
1945         * idle object evictor thread (if any).
1946         * <p>
1947         * When a negative value is supplied, <code>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</code>
1948         * tests will be run.  I.e., when the value is <code>-n</code>, roughly one <code>n</code>th of the
1949         * idle objects will be tested per run.
1950         *
1951         * @see #setNumTestsPerEvictionRun
1952         * @see #getNumTestsPerEvictionRun
1953         * @see #getTimeBetweenEvictionRunsMillis
1954         * @see #setTimeBetweenEvictionRunsMillis
1955         */
1956        private int _numTestsPerEvictionRun =  DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1957    
1958        /**
1959         * The minimum amount of time an object may sit idle in the pool
1960         * before it is eligible for eviction by the idle object evictor
1961         * (if any).
1962         * When non-positive, no objects will be evicted from the pool
1963         * due to idle time alone.
1964         *
1965         * @see #setMinEvictableIdleTimeMillis
1966         * @see #getMinEvictableIdleTimeMillis
1967         * @see #getTimeBetweenEvictionRunsMillis
1968         * @see #setTimeBetweenEvictionRunsMillis
1969         */
1970        private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1971    
1972        /** My hash of pools (ObjectQueue). */
1973        private Map _poolMap = null;
1974    
1975        /** The total number of active instances. */
1976        private int _totalActive = 0;
1977    
1978        /** The total number of idle instances. */
1979        private int _totalIdle = 0;
1980    
1981        /** My {@link KeyedPoolableObjectFactory}. */
1982        private KeyedPoolableObjectFactory _factory = null;
1983    
1984        /**
1985         * My idle object eviction {@link TimerTask}, if any.
1986         */
1987        private Evictor _evictor = null;
1988    
1989        /**
1990         * A cursorable list of my pools.
1991         * @see GenericKeyedObjectPool.Evictor#run
1992         */
1993        private CursorableLinkedList _poolList = null;
1994        
1995        private CursorableLinkedList.Cursor _evictionCursor = null;
1996        private CursorableLinkedList.Cursor _evictionKeyCursor = null;
1997        
1998        /** Whether or not the pools behave as LIFO queues (last in first out) */
1999        private boolean _lifo = DEFAULT_LIFO;
2000    }