1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool.impl;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.ListIterator;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24 import java.util.Set;
25 import java.util.TreeMap;
26 import java.util.LinkedList;
27 import java.util.HashSet;
28 import java.util.TimerTask;
29
30 import org.apache.commons.pool.BaseKeyedObjectPool;
31 import org.apache.commons.pool.KeyedObjectPool;
32 import org.apache.commons.pool.KeyedPoolableObjectFactory;
33
34 /***
35 * A configurable {@link KeyedObjectPool} implementation.
36 * <p>
37 * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
38 * <tt>GenericKeyedObjectPool</tt> provides robust pooling functionality for
39 * arbitrary objects.
40 * <p>
41 * A <tt>GenericKeyedObjectPool</tt> provides a number of configurable parameters:
42 * <ul>
43 * <li>
44 * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects (per key)
45 * that can be borrowed from the pool at one time. When non-positive, there
46 * is no limit to the number of objects that may be active at one time.
47 * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
48 * </li>
49 * <li>
50 * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
51 * sit idle in the pool (per key) at any time. When negative, there
52 * is no limit to the number of objects that may be idle at one time.
53 * </li>
54 * <li>
55 * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
56 * behaviour of the {@link #borrowObject} method when the pool is exhausted:
57 * <ul>
58 * <li>
59 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
60 * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
61 * a {@link NoSuchElementException}
62 * </li>
63 * <li>
64 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
65 * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
66 * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
67 * meaningless.)
68 * </li>
69 * <li>
70 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
71 * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
72 * (invoke {@link Object#wait} until a new or idle object is available.
73 * If a positive {@link #setMaxWait <i>maxWait</i>}
74 * value is supplied, the {@link #borrowObject} will block for at
75 * most that many milliseconds, after which a {@link NoSuchElementException}
76 * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive,
77 * the {@link #borrowObject} method will block indefinitely.
78 * </li>
79 * </ul>
80 * </li>
81 * <li>
82 * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
83 * attempt to validate each object before it is returned from the
84 * {@link #borrowObject} method. (Using the provided factory's
85 * {@link KeyedPoolableObjectFactory#validateObject} method.) Objects that fail
86 * to validate will be dropped from the pool, and a different object will
87 * be borrowed.
88 * </li>
89 * <li>
90 * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
91 * attempt to validate each object before it is returned to the pool in the
92 * {@link #returnObject} method. (Using the provided factory's
93 * {@link KeyedPoolableObjectFactory#validateObject}
94 * method.) Objects that fail to validate will be dropped from the pool.
95 * </li>
96 * </ul>
97 * <p>
98 * Optionally, one may configure the pool to examine and possibly evict objects as they
99 * sit idle in the pool. This is performed by an "idle object eviction" thread, which
100 * runs asychronously. The idle object eviction thread may be configured using the
101 * following attributes:
102 * <ul>
103 * <li>
104 * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
105 * indicates how long the eviction thread should sleep before "runs" of examining
106 * idle objects. When non-positive, no eviction thread will be launched.
107 * </li>
108 * <li>
109 * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
110 * specifies the minimum amount of time that an object may sit idle in the pool
111 * before it is eligable for eviction due to idle time. When non-positive, no object
112 * will be dropped from the pool due to idle time alone.
113 * </li>
114 * <li>
115 * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
116 * objects should be validated using the factory's
117 * {@link KeyedPoolableObjectFactory#validateObject} method. Objects
118 * that fail to validate will be dropped from the pool.
119 * </li>
120 * </ul>
121 * <p>
122 * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}. A
123 * non-<code>null</code> factory must be provided either as a constructor argument
124 * or via a call to {@link #setFactory} before the pool is used.
125 * </p>
126 * @see GenericObjectPool
127 * @author Rodney Waldhoff
128 * @author Dirk Verbeeck
129 * @version $Revision: 386116 $ $Date: 2006-03-15 12:15:58 -0500 (Wed, 15 Mar 2006) $
130 */
131 public class GenericKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
132
133
134
135 /***
136 * A "when exhausted action" type indicating that when the pool is
137 * exhausted (i.e., the maximum number of active objects has
138 * been reached), the {@link #borrowObject}
139 * method should fail, throwing a {@link NoSuchElementException}.
140 * @see #WHEN_EXHAUSTED_BLOCK
141 * @see #WHEN_EXHAUSTED_GROW
142 * @see #setWhenExhaustedAction
143 */
144 public static final byte WHEN_EXHAUSTED_FAIL = 0;
145
146 /***
147 * A "when exhausted action" type indicating that when the pool
148 * is exhausted (i.e., the maximum number
149 * of active objects has been reached), the {@link #borrowObject}
150 * method should block until a new object is available, or the
151 * {@link #getMaxWait maximum wait time} has been reached.
152 * @see #WHEN_EXHAUSTED_FAIL
153 * @see #WHEN_EXHAUSTED_GROW
154 * @see #setMaxWait
155 * @see #getMaxWait
156 * @see #setWhenExhaustedAction
157 */
158 public static final byte WHEN_EXHAUSTED_BLOCK = 1;
159
160 /***
161 * A "when exhausted action" type indicating that when the pool is
162 * exhausted (i.e., the maximum number
163 * of active objects has been reached), the {@link #borrowObject}
164 * method should simply create a new object anyway.
165 * @see #WHEN_EXHAUSTED_FAIL
166 * @see #WHEN_EXHAUSTED_GROW
167 * @see #setWhenExhaustedAction
168 */
169 public static final byte WHEN_EXHAUSTED_GROW = 2;
170
171 /***
172 * The default cap on the number of idle instances in the pool
173 * (per key).
174 * @see #getMaxIdle
175 * @see #setMaxIdle
176 */
177 public static final int DEFAULT_MAX_IDLE = 8;
178
179 /***
180 * The default cap on the total number of active instances from the pool
181 * (per key).
182 * @see #getMaxActive
183 * @see #setMaxActive
184 */
185 public static final int DEFAULT_MAX_ACTIVE = 8;
186
187 /***
188 * The default cap on the the maximum number of objects that can exists at one time.
189 * @see #getMaxTotal
190 * @see #setMaxTotal
191 */
192 public static final int DEFAULT_MAX_TOTAL = -1;
193
194 /***
195 * The default "when exhausted action" for the pool.
196 * @see #WHEN_EXHAUSTED_BLOCK
197 * @see #WHEN_EXHAUSTED_FAIL
198 * @see #WHEN_EXHAUSTED_GROW
199 * @see #setWhenExhaustedAction
200 */
201 public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
202
203 /***
204 * The default maximum amount of time (in millis) the
205 * {@link #borrowObject} method should block before throwing
206 * an exception when the pool is exhausted and the
207 * {@link #getWhenExhaustedAction "when exhausted" action} is
208 * {@link #WHEN_EXHAUSTED_BLOCK}.
209 * @see #getMaxWait
210 * @see #setMaxWait
211 */
212 public static final long DEFAULT_MAX_WAIT = -1L;
213
214 /***
215 * The default "test on borrow" value.
216 * @see #getTestOnBorrow
217 * @see #setTestOnBorrow
218 */
219 public static final boolean DEFAULT_TEST_ON_BORROW = false;
220
221 /***
222 * The default "test on return" value.
223 * @see #getTestOnReturn
224 * @see #setTestOnReturn
225 */
226 public static final boolean DEFAULT_TEST_ON_RETURN = false;
227
228 /***
229 * The default "test while idle" value.
230 * @see #getTestWhileIdle
231 * @see #setTestWhileIdle
232 * @see #getTimeBetweenEvictionRunsMillis
233 * @see #setTimeBetweenEvictionRunsMillis
234 */
235 public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
236
237 /***
238 * The default "time between eviction runs" value.
239 * @see #getTimeBetweenEvictionRunsMillis
240 * @see #setTimeBetweenEvictionRunsMillis
241 */
242 public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
243
244 /***
245 * The default number of objects to examine per run in the
246 * idle object evictor.
247 * @see #getNumTestsPerEvictionRun
248 * @see #setNumTestsPerEvictionRun
249 * @see #getTimeBetweenEvictionRunsMillis
250 * @see #setTimeBetweenEvictionRunsMillis
251 */
252 public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
253
254 /***
255 * The default value for {@link #getMinEvictableIdleTimeMillis}.
256 * @see #getMinEvictableIdleTimeMillis
257 * @see #setMinEvictableIdleTimeMillis
258 */
259 public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
260
261 /***
262 * The default minimum level of idle objects in the pool.
263 * @see #setMinIdle
264 * @see #getMinIdle
265 */
266 public static final int DEFAULT_MIN_IDLE = 0;
267
268
269
270 /***
271 * Create a new <tt>GenericKeyedObjectPool</tt>..
272 */
273 public GenericKeyedObjectPool() {
274 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);
275 }
276
277 /***
278 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
279 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
280 */
281 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) {
282 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);
283 }
284
285 /***
286 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
287 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
288 * @param config a non-<tt>null</tt> {@link GenericKeyedObjectPool.Config} describing my configuration
289 */
290 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
291 this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
292 }
293
294 /***
295 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
296 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
297 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
298 */
299 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
300 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);
301 }
302
303 /***
304 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
305 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
306 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
307 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
308 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
309 */
310 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
311 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);
312 }
313
314 /***
315 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
316 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
317 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
318 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
319 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
320 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
321 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
322 */
323 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
324 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);
325 }
326
327 /***
328 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
329 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
330 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
331 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
332 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
333 * @param maxIdle the maximum number of idle objects in my pool (per key) (see {@link #setMaxIdle})
334 */
335 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
336 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);
337 }
338
339 /***
340 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
341 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
342 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
343 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
344 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
345 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
346 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
347 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
348 */
349 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
350 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);
351 }
352
353 /***
354 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
355 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
356 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
357 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
358 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
359 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
360 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
361 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
362 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
363 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
364 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
365 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
366 */
367 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
368 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
369 }
370
371 /***
372 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
373 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
374 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
375 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
376 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
377 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
378 * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
379 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
380 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
381 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
382 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
383 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
384 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
385 */
386 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
387 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
388 }
389
390 /***
391 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
392 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
393 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
394 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
395 * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
396 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
397 * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
398 * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
399 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
400 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
401 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
402 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
403 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
404 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
405 */
406 public GenericKeyedObjectPool(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) {
407 _factory = factory;
408 _maxActive = maxActive;
409 switch(whenExhaustedAction) {
410 case WHEN_EXHAUSTED_BLOCK:
411 case WHEN_EXHAUSTED_FAIL:
412 case WHEN_EXHAUSTED_GROW:
413 _whenExhaustedAction = whenExhaustedAction;
414 break;
415 default:
416 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
417 }
418 _maxWait = maxWait;
419 _maxIdle = maxIdle;
420 _maxTotal = maxTotal;
421 _minIdle = minIdle;
422 _testOnBorrow = testOnBorrow;
423 _testOnReturn = testOnReturn;
424 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
425 _numTestsPerEvictionRun = numTestsPerEvictionRun;
426 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
427 _testWhileIdle = testWhileIdle;
428
429 _poolMap = new HashMap();
430 _activeMap = new HashMap();
431
432 startEvictor(_timeBetweenEvictionRunsMillis);
433 }
434
435
436
437
438
439 /***
440 * Returns the cap on the number of active instances from my pool (per key).
441 * @return the cap on the number of active instances from my pool (per key).
442 * @see #setMaxActive
443 */
444 public synchronized int getMaxActive() {
445 return _maxActive;
446 }
447
448 /***
449 * Sets the cap on the number of active instances from my pool (per key).
450 * @param maxActive The cap on the number of active instances from my pool (per key).
451 * Use a negative value for an infinite number of instances.
452 * @see #getMaxActive
453 */
454 public synchronized void setMaxActive(int maxActive) {
455 _maxActive = maxActive;
456 notifyAll();
457 }
458
459 /***
460 * Returns the cap on the total number of instances from my pool if non-positive.
461 * @return the cap on the total number of instances from my pool if non-positive.
462 * @see #setMaxTotal
463 */
464 public synchronized int getMaxTotal() {
465 return _maxTotal;
466 }
467
468 /***
469 * Sets the cap on the total number of instances from my pool if non-positive.
470 * @param maxTotal The cap on the total number of instances from my pool.
471 * Use a non-positive value for an infinite number of instances.
472 * @see #getMaxTotal
473 */
474 public synchronized void setMaxTotal(int maxTotal) {
475 _maxTotal = maxTotal;
476 notifyAll();
477 }
478
479 /***
480 * Returns the action to take when the {@link #borrowObject} method
481 * is invoked when the pool is exhausted (the maximum number
482 * of "active" objects has been reached).
483 *
484 * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
485 * @see #setWhenExhaustedAction
486 */
487 public synchronized byte getWhenExhaustedAction() {
488 return _whenExhaustedAction;
489 }
490
491 /***
492 * Sets the action to take when the {@link #borrowObject} method
493 * is invoked when the pool is exhausted (the maximum number
494 * of "active" objects has been reached).
495 *
496 * @param whenExhaustedAction the action code, which must be one of
497 * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
498 * or {@link #WHEN_EXHAUSTED_GROW}
499 * @see #getWhenExhaustedAction
500 */
501 public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
502 switch(whenExhaustedAction) {
503 case WHEN_EXHAUSTED_BLOCK:
504 case WHEN_EXHAUSTED_FAIL:
505 case WHEN_EXHAUSTED_GROW:
506 _whenExhaustedAction = whenExhaustedAction;
507 notifyAll();
508 break;
509 default:
510 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
511 }
512 }
513
514
515 /***
516 * Returns the maximum amount of time (in milliseconds) the
517 * {@link #borrowObject} method should block before throwing
518 * an exception when the pool is exhausted and the
519 * {@link #setWhenExhaustedAction "when exhausted" action} is
520 * {@link #WHEN_EXHAUSTED_BLOCK}.
521 *
522 * When less than 0, the {@link #borrowObject} method
523 * may block indefinitely.
524 *
525 * @see #setMaxWait
526 * @see #setWhenExhaustedAction
527 * @see #WHEN_EXHAUSTED_BLOCK
528 */
529 public synchronized long getMaxWait() {
530 return _maxWait;
531 }
532
533 /***
534 * Sets the maximum amount of time (in milliseconds) the
535 * {@link #borrowObject} method should block before throwing
536 * an exception when the pool is exhausted and the
537 * {@link #setWhenExhaustedAction "when exhausted" action} is
538 * {@link #WHEN_EXHAUSTED_BLOCK}.
539 *
540 * When less than 0, the {@link #borrowObject} method
541 * may block indefinitely.
542 *
543 * @see #getMaxWait
544 * @see #setWhenExhaustedAction
545 * @see #WHEN_EXHAUSTED_BLOCK
546 */
547 public synchronized void setMaxWait(long maxWait) {
548 _maxWait = maxWait;
549 }
550
551 /***
552 * Returns the cap on the number of "idle" instances in the pool.
553 * @return the cap on the number of "idle" instances in the pool.
554 * @see #setMaxIdle
555 */
556 public synchronized int getMaxIdle() {
557 return _maxIdle;
558 }
559
560 /***
561 * Sets the cap on the number of "idle" instances in the pool.
562 * @param maxIdle The cap on the number of "idle" instances in the pool.
563 * Use a negative value to indicate an unlimited number
564 * of idle instances.
565 * @see #getMaxIdle
566 */
567 public synchronized void setMaxIdle(int maxIdle) {
568 _maxIdle = maxIdle;
569 notifyAll();
570 }
571
572 /***
573 * Sets the minimum number of idle objects in pool to maintain (per key)
574 * @param poolSize - The minimum size of the pool
575 * @see #getMinIdle
576 */
577 public synchronized void setMinIdle(int poolSize) {
578 _minIdle = poolSize;
579 }
580
581 /***
582 * Returns the minimum number of idle objects in pool to maintain (per key)
583 * @return the minimum number of idle objects in pool to maintain (per key)
584 * @see #setMinIdle
585 */
586 public synchronized int getMinIdle() {
587 return _minIdle;
588 }
589
590 /***
591 * When <tt>true</tt>, objects will be
592 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
593 * before being returned by the {@link #borrowObject}
594 * method. If the object fails to validate,
595 * it will be dropped from the pool, and we will attempt
596 * to borrow another.
597 *
598 * @see #setTestOnBorrow
599 */
600 public synchronized boolean getTestOnBorrow() {
601 return _testOnBorrow;
602 }
603
604 /***
605 * When <tt>true</tt>, objects will be
606 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
607 * before being returned by the {@link #borrowObject}
608 * method. If the object fails to validate,
609 * it will be dropped from the pool, and we will attempt
610 * to borrow another.
611 *
612 * @see #getTestOnBorrow
613 */
614 public synchronized void setTestOnBorrow(boolean testOnBorrow) {
615 _testOnBorrow = testOnBorrow;
616 }
617
618 /***
619 * When <tt>true</tt>, objects will be
620 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
621 * before being returned to the pool within the
622 * {@link #returnObject}.
623 *
624 * @see #setTestOnReturn
625 */
626 public synchronized boolean getTestOnReturn() {
627 return _testOnReturn;
628 }
629
630 /***
631 * When <tt>true</tt>, objects will be
632 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
633 * before being returned to the pool within the
634 * {@link #returnObject}.
635 *
636 * @see #getTestOnReturn
637 */
638 public synchronized void setTestOnReturn(boolean testOnReturn) {
639 _testOnReturn = testOnReturn;
640 }
641
642 /***
643 * Returns the number of milliseconds to sleep between runs of the
644 * idle object evictor thread.
645 * When non-positive, no idle object evictor thread will be
646 * run.
647 *
648 * @see #setTimeBetweenEvictionRunsMillis
649 */
650 public synchronized long getTimeBetweenEvictionRunsMillis() {
651 return _timeBetweenEvictionRunsMillis;
652 }
653
654 /***
655 * Sets the number of milliseconds to sleep between runs of the
656 * idle object evictor thread.
657 * When non-positive, no idle object evictor thread will be
658 * run.
659 *
660 * @see #getTimeBetweenEvictionRunsMillis
661 */
662 public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
663 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
664 startEvictor(_timeBetweenEvictionRunsMillis);
665 }
666
667 /***
668 * Returns the number of objects to examine during each run of the
669 * idle object evictor thread (if any).
670 *
671 * @see #setNumTestsPerEvictionRun
672 * @see #setTimeBetweenEvictionRunsMillis
673 */
674 public synchronized int getNumTestsPerEvictionRun() {
675 return _numTestsPerEvictionRun;
676 }
677
678 /***
679 * Sets the number of objects to examine during each run of the
680 * idle object evictor thread (if any).
681 * <p>
682 * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
683 * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
684 * idle objects will be tested per run.
685 *
686 * @see #getNumTestsPerEvictionRun
687 * @see #setTimeBetweenEvictionRunsMillis
688 */
689 public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
690 _numTestsPerEvictionRun = numTestsPerEvictionRun;
691 }
692
693 /***
694 * Returns the minimum amount of time an object may sit idle in the pool
695 * before it is eligable for eviction by the idle object evictor
696 * (if any).
697 *
698 * @see #setMinEvictableIdleTimeMillis
699 * @see #setTimeBetweenEvictionRunsMillis
700 */
701 public synchronized long getMinEvictableIdleTimeMillis() {
702 return _minEvictableIdleTimeMillis;
703 }
704
705 /***
706 * Sets the minimum amount of time an object may sit idle in the pool
707 * before it is eligable for eviction by the idle object evictor
708 * (if any).
709 * When non-positive, no objects will be evicted from the pool
710 * due to idle time alone.
711 *
712 * @see #getMinEvictableIdleTimeMillis
713 * @see #setTimeBetweenEvictionRunsMillis
714 */
715 public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
716 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
717 }
718
719 /***
720 * When <tt>true</tt>, objects will be
721 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
722 * by the idle object evictor (if any). If an object
723 * fails to validate, it will be dropped from the pool.
724 *
725 * @see #setTestWhileIdle
726 * @see #setTimeBetweenEvictionRunsMillis
727 */
728 public synchronized boolean getTestWhileIdle() {
729 return _testWhileIdle;
730 }
731
732 /***
733 * When <tt>true</tt>, objects will be
734 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
735 * by the idle object evictor (if any). If an object
736 * fails to validate, it will be dropped from the pool.
737 *
738 * @see #getTestWhileIdle
739 * @see #setTimeBetweenEvictionRunsMillis
740 */
741 public synchronized void setTestWhileIdle(boolean testWhileIdle) {
742 _testWhileIdle = testWhileIdle;
743 }
744
745 /***
746 * Sets my configuration.
747 * @see GenericKeyedObjectPool.Config
748 */
749 public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
750 setMaxIdle(conf.maxIdle);
751 setMaxActive(conf.maxActive);
752 setMaxTotal(conf.maxTotal);
753 setMinIdle(conf.minIdle);
754 setMaxWait(conf.maxWait);
755 setWhenExhaustedAction(conf.whenExhaustedAction);
756 setTestOnBorrow(conf.testOnBorrow);
757 setTestOnReturn(conf.testOnReturn);
758 setTestWhileIdle(conf.testWhileIdle);
759 setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
760 setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
761 setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
762 }
763
764
765
766 public synchronized Object borrowObject(Object key) throws Exception {
767 long starttime = System.currentTimeMillis();
768 boolean newlyCreated = false;
769 for(;;) {
770 LinkedList pool = (LinkedList)(_poolMap.get(key));
771 if(null == pool) {
772 pool = new LinkedList();
773 _poolMap.put(key,pool);
774 }
775 ObjectTimestampPair pair = null;
776
777 try {
778 pair = (ObjectTimestampPair)(pool.removeFirst());
779 if(null != pair) {
780 _totalIdle--;
781 }
782 } catch(NoSuchElementException e) {
783 }
784
785 if(null == pair) {
786
787
788 if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
789 clearOldest();
790 }
791
792
793
794 int active = getActiveCount(key);
795 if ((_maxActive < 0 || active < _maxActive) &&
796 (_maxTotal < 0 || _totalActive + _totalIdle < _maxTotal)) {
797 Object obj = _factory.makeObject(key);
798 pair = new ObjectTimestampPair(obj);
799 newlyCreated = true;
800 } else {
801
802 switch(_whenExhaustedAction) {
803 case WHEN_EXHAUSTED_GROW:
804 Object obj = _factory.makeObject(key);
805 pair = new ObjectTimestampPair(obj);
806 break;
807 case WHEN_EXHAUSTED_FAIL:
808 throw new NoSuchElementException();
809 case WHEN_EXHAUSTED_BLOCK:
810 try {
811 if(_maxWait <= 0) {
812 wait();
813 } else {
814
815
816 final long elapsed = (System.currentTimeMillis() - starttime);
817 final long waitTime = _maxWait - elapsed;
818 if (waitTime > 0)
819 {
820 wait(waitTime);
821 }
822 }
823 } catch(InterruptedException e) {
824
825 }
826 if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
827 throw new NoSuchElementException("Timeout waiting for idle object");
828 } else {
829 continue;
830 }
831 default:
832 throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
833 }
834 }
835 }
836 _factory.activateObject(key,pair.value);
837 if(_testOnBorrow && !_factory.validateObject(key,pair.value)) {
838 _factory.destroyObject(key,pair.value);
839 if(newlyCreated) {
840 throw new NoSuchElementException("Could not create a validated object");
841 }
842 } else {
843 incrementActiveCount(key);
844 return pair.value;
845 }
846 }
847 }
848
849 public synchronized void clear() {
850 for(Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext(); ) {
851 Object key = keyiter.next();
852 final LinkedList list = (LinkedList)(_poolMap.get(key));
853 for(Iterator it = list.iterator(); it.hasNext(); ) {
854 try {
855 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
856 } catch(Exception e) {
857
858 }
859 it.remove();
860 }
861 }
862 _poolMap.clear();
863 if (_recentlyEvictedKeys != null) {
864 _recentlyEvictedKeys.clear();
865 }
866 _totalIdle = 0;
867 notifyAll();
868 }
869
870 /***
871 * Method clears oldest 15% of objects in pool. The method sorts the
872 * objects into a TreeMap and then iterates the first 15% for removal
873 */
874 public synchronized void clearOldest() {
875
876 TreeMap map = new TreeMap();
877 for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) {
878 Object key = keyiter.next();
879 LinkedList list = (LinkedList) _poolMap.get(key);
880 for (Iterator it = list.iterator(); it.hasNext();) {
881
882
883
884 ObjectTimestampPair pair = (ObjectTimestampPair) it.next();
885 map.put(pair, key);
886 }
887 }
888
889
890 Set setPairKeys = map.entrySet();
891 int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
892
893 Iterator iter = setPairKeys.iterator();
894 while (iter.hasNext() && itemsToRemove > 0) {
895 Map.Entry entry = (Map.Entry) iter.next();
896
897
898
899 Object key = entry.getValue();
900 ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey();
901 LinkedList list = (LinkedList) _poolMap.get(key);
902 list.remove(pairTimeStamp);
903
904 try {
905 _factory.destroyObject(key, pairTimeStamp.value);
906 } catch (Exception e) {
907
908 }
909
910 if (list.isEmpty()) {
911 _poolMap.remove(key);
912 }
913 _totalIdle--;
914 itemsToRemove--;
915 }
916 notifyAll();
917 }
918
919 public synchronized void clear(Object key) {
920 LinkedList pool = (LinkedList)(_poolMap.remove(key));
921 if(null == pool) {
922 return;
923 } else {
924 for(Iterator it = pool.iterator(); it.hasNext(); ) {
925 try {
926 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
927 } catch(Exception e) {
928
929 }
930 it.remove();
931 _totalIdle--;
932 }
933 }
934 notifyAll();
935 }
936
937 public synchronized int getNumActive() {
938 return _totalActive;
939 }
940
941 public synchronized int getNumIdle() {
942 return _totalIdle;
943 }
944
945 public synchronized int getNumActive(Object key) {
946 return getActiveCount(key);
947 }
948
949 public synchronized int getNumIdle(Object key) {
950 try {
951 return((LinkedList)(_poolMap.get(key))).size();
952 } catch(Exception e) {
953 return 0;
954 }
955 }
956
957 public synchronized void returnObject(Object key, Object obj) throws Exception {
958
959
960 boolean success = true;
961 if(_testOnReturn && !_factory.validateObject(key, obj)) {
962 success = false;
963 try {
964 _factory.destroyObject(key, obj);
965 } catch(Exception e) {
966
967 }
968 } else {
969 try {
970 _factory.passivateObject(key, obj);
971 } catch(Exception e) {
972 success = false;
973 }
974 }
975
976 boolean shouldDestroy = false;
977
978 LinkedList pool = (LinkedList) (_poolMap.get(key));
979
980 if(null == pool) {
981 pool = new LinkedList();
982 _poolMap.put(key, pool);
983 }
984 decrementActiveCount(key);
985
986
987 if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
988 shouldDestroy = true;
989 } else if(success) {
990 pool.addLast(new ObjectTimestampPair(obj));
991 _totalIdle++;
992 }
993 notifyAll();
994
995 if(shouldDestroy) {
996 try {
997 _factory.destroyObject(key, obj);
998 } catch(Exception e) {
999
1000 }
1001 }
1002 }
1003
1004 public synchronized void invalidateObject(Object key, Object obj) throws Exception {
1005 try {
1006 _factory.destroyObject(key, obj);
1007 }
1008 finally {
1009 decrementActiveCount(key);
1010 notifyAll();
1011 }
1012 }
1013
1014 public synchronized void addObject(Object key) throws Exception {
1015 Object obj = _factory.makeObject(key);
1016 incrementActiveCount(key);
1017 returnObject(key,obj);
1018 }
1019
1020 /***
1021 * Registers a key for pool control.
1022 *
1023 * If <i>populateImmediately</i> is <code>true</code>, the pool will immediately commence
1024 * a sustain cycle. If <i>populateImmediately</i> is <code>false</code>, the pool will be
1025 * populated when the next schedules sustain task is run.
1026 *
1027 * @param key - The key to register for pool control.
1028 * @param populateImmediately - If this is <code>true</code>, the pool
1029 * will start a sustain cycle immediately.
1030 */
1031 public synchronized void preparePool(Object key, boolean populateImmediately) {
1032 LinkedList pool = (LinkedList)(_poolMap.get(key));
1033 if (null == pool) {
1034 pool = new LinkedList();
1035 _poolMap.put(key,pool);
1036 }
1037
1038 if (populateImmediately) {
1039 try {
1040
1041 ensureMinIdle(key);
1042 }
1043 catch (Exception e) {
1044
1045 }
1046 }
1047 }
1048
1049 public synchronized void close() throws Exception {
1050 clear();
1051 _poolMap = null;
1052 _activeMap = null;
1053 _recentlyEvictedKeys = null;
1054 if(null != _evictor) {
1055 _evictor.cancel();
1056 _evictor = null;
1057 }
1058 }
1059
1060 public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
1061 if(0 < getNumActive()) {
1062 throw new IllegalStateException("Objects are already active");
1063 } else {
1064 clear();
1065 _factory = factory;
1066 }
1067 }
1068
1069 public synchronized void evict() throws Exception {
1070 Object key = null;
1071 if (_recentlyEvictedKeys == null) {
1072 _recentlyEvictedKeys = new HashSet(_poolMap.size());
1073 }
1074 Set remainingKeys = new HashSet(_poolMap.keySet());
1075 remainingKeys.removeAll(_recentlyEvictedKeys);
1076 Iterator keyIter = remainingKeys.iterator();
1077
1078 ListIterator objIter = null;
1079
1080 for(int i=0,m=getNumTests();i<m;i++) {
1081 if(_poolMap.size() > 0) {
1082
1083 if (key == null) {
1084 if (!keyIter.hasNext()) {
1085 _recentlyEvictedKeys.clear();
1086 remainingKeys = new HashSet(_poolMap.keySet());
1087 keyIter = remainingKeys.iterator();
1088 }
1089 if (!keyIter.hasNext()) {
1090
1091 return;
1092 }
1093 key = keyIter.next();
1094 }
1095
1096
1097 if (objIter == null) {
1098 final LinkedList list = (LinkedList)_poolMap.get(key);
1099 if (_evictLastIndex < 0 || _evictLastIndex > list.size()) {
1100 _evictLastIndex = list.size();
1101 }
1102 objIter = list.listIterator(_evictLastIndex);
1103 }
1104
1105
1106 if(objIter.hasPrevious()) {
1107 ObjectTimestampPair pair = (ObjectTimestampPair)(objIter.previous());
1108 boolean removeObject=false;
1109 if(_minEvictableIdleTimeMillis > 0 &&
1110 System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
1111 removeObject=true;
1112 }
1113 if(_testWhileIdle && removeObject == false) {
1114 boolean active = false;
1115 try {
1116 _factory.activateObject(key,pair.value);
1117 active = true;
1118 } catch(Exception e) {
1119 removeObject=true;
1120 }
1121 if(active) {
1122 if(!_factory.validateObject(key,pair.value)) {
1123 removeObject=true;
1124 } else {
1125 try {
1126 _factory.passivateObject(key,pair.value);
1127 } catch(Exception e) {
1128 removeObject=true;
1129 }
1130 }
1131 }
1132 }
1133 if(removeObject) {
1134 try {
1135 objIter.remove();
1136 _totalIdle--;
1137 _factory.destroyObject(key,pair.value);
1138
1139
1140
1141
1142
1143
1144 if ((_minIdle == 0) && (((LinkedList)(_poolMap.get(key))).isEmpty())) {
1145 _poolMap.remove(key);
1146 }
1147 } catch(Exception e) {
1148 ;
1149 }
1150 }
1151 } else {
1152
1153 _recentlyEvictedKeys.add(key);
1154 _evictLastIndex = -1;
1155 objIter = null;
1156 }
1157 }
1158 }
1159 }
1160
1161 /***
1162 * Iterates through all the known keys and creates any necessary objects to maintain
1163 * the minimum level of pooled objects.
1164 * @see #getMinIdle
1165 * @see #setMinIdle
1166 * @throws Exception If there was an error whilst creating the pooled objects.
1167 */
1168 private synchronized void ensureMinIdle() throws Exception {
1169 Iterator iterator = _poolMap.keySet().iterator();
1170
1171
1172 if (_minIdle > 0) {
1173
1174
1175
1176
1177 while (iterator.hasNext()) {
1178
1179 Object key = iterator.next();
1180 ensureMinIdle(key);
1181 }
1182 }
1183 }
1184
1185 /***
1186 * Re-creates any needed objects to maintain the minimum levels of
1187 * pooled objects for the specified key.
1188 *
1189 * This method uses {@link #calculateDefecit} to calculate the number
1190 * of objects to be created. {@link #calculateDefecit} can be overridden to
1191 * provide a different method of calculating the number of objects to be
1192 * created.
1193 * @param key The key to process
1194 * @throws Exception If there was an error whilst creating the pooled objects
1195 */
1196 private synchronized void ensureMinIdle(Object key) throws Exception {
1197
1198 int numberToCreate = calculateDefecit(key);
1199
1200
1201 for (int i = 0; i < numberToCreate; i++) {
1202 addObject(key);
1203 }
1204 }
1205
1206
1207
1208 /***
1209 * Start the eviction thread or service, or when
1210 * <i>delay</i> is non-positive, stop it
1211 * if it is already running.
1212 */
1213 protected synchronized void startEvictor(long delay) {
1214 if(null != _evictor) {
1215 _evictor.cancel();
1216 _evictor = null;
1217 }
1218 if(delay > 0) {
1219 _evictor = new Evictor();
1220 GenericObjectPool.EVICTION_TIMER.schedule(_evictor, delay, delay);
1221 }
1222 }
1223
1224 synchronized String debugInfo() {
1225 StringBuffer buf = new StringBuffer();
1226 buf.append("Active: ").append(getNumActive()).append("\n");
1227 buf.append("Idle: ").append(getNumIdle()).append("\n");
1228 Iterator it = _poolMap.keySet().iterator();
1229 while(it.hasNext()) {
1230 buf.append("\t").append(_poolMap.get(it.next())).append("\n");
1231 }
1232 return buf.toString();
1233 }
1234
1235 private int getNumTests() {
1236 if(_numTestsPerEvictionRun >= 0) {
1237 return _numTestsPerEvictionRun;
1238 } else {
1239 return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
1240 }
1241 }
1242
1243 private void incrementActiveCount(Object key) {
1244 _totalActive++;
1245 Integer active = (Integer)(_activeMap.get(key));
1246 if(null == active) {
1247 _activeMap.put(key,new Integer(1));
1248 } else {
1249 _activeMap.put(key,new Integer(active.intValue() + 1));
1250 }
1251 }
1252
1253 private void decrementActiveCount(Object key) {
1254 _totalActive--;
1255 Integer active = (Integer)(_activeMap.get(key));
1256 if(null == active) {
1257
1258 } else if(active.intValue() <= 1) {
1259 _activeMap.remove(key);
1260 } else {
1261 _activeMap.put(key, new Integer(active.intValue() - 1));
1262 }
1263 }
1264
1265 private int getActiveCount(Object key) {
1266 int active = 0;
1267 Integer act = (Integer)(_activeMap.get(key));
1268 if(null != act) {
1269 active = act.intValue();
1270 }
1271 return active;
1272 }
1273
1274 /***
1275 * This returns the number of objects to create during the pool
1276 * sustain cycle. This will ensure that the minimum number of idle
1277 * connections is maintained without going past the maxPool value.
1278 * <p>
1279 * This method has been left public so derived classes can override
1280 * the way the defecit is calculated. ie... Increase/decrease the pool
1281 * size at certain times of day to accomodate for usage patterns.
1282 *
1283 * @param key - The key of the pool to calculate the number of
1284 * objects to be re-created
1285 * @return The number of objects to be created
1286 */
1287 private int calculateDefecit(Object key) {
1288 int objectDefecit = 0;
1289
1290
1291
1292 objectDefecit = getMinIdle() - getNumIdle(key);
1293 if (getMaxActive() > 0) {
1294 int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
1295 objectDefecit = Math.min(objectDefecit, growLimit);
1296 }
1297
1298
1299 if (getMaxTotal() > 0) {
1300 int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
1301 objectDefecit = Math.min(objectDefecit, growLimit);
1302 }
1303
1304 return objectDefecit;
1305 }
1306
1307
1308
1309 /***
1310 * A simple "struct" encapsulating an object instance and a timestamp.
1311 *
1312 * Implements Comparable, objects are sorted from old to new.
1313 *
1314 * This is also used by {@link GenericObjectPool}.
1315 */
1316 static class ObjectTimestampPair implements Comparable {
1317 Object value;
1318 long tstamp;
1319
1320 ObjectTimestampPair(Object val) {
1321 this(val, System.currentTimeMillis());
1322 }
1323
1324 ObjectTimestampPair(Object val, long time) {
1325 value = val;
1326 tstamp = time;
1327 }
1328
1329 public String toString() {
1330 return value + ";" + tstamp;
1331 }
1332
1333 public int compareTo(Object obj) {
1334 return compareTo((ObjectTimestampPair) obj);
1335 }
1336
1337 public int compareTo(ObjectTimestampPair other) {
1338 return (int) (this.tstamp - other.tstamp);
1339 }
1340 }
1341
1342 /***
1343 * The idle object evictor {@link TimerTask}.
1344 * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1345 */
1346 private class Evictor extends TimerTask {
1347 public void run() {
1348
1349 try {
1350 evict();
1351 } catch(Exception e) {
1352
1353 }
1354
1355 try {
1356 ensureMinIdle();
1357 } catch (Exception e) {
1358
1359 }
1360 }
1361 }
1362
1363 /***
1364 * A simple "struct" encapsulating the
1365 * configuration information for a {@link GenericKeyedObjectPool}.
1366 * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
1367 * @see GenericKeyedObjectPool#setConfig
1368 */
1369 public static class Config {
1370 public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
1371 public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
1372 public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
1373 public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE;
1374 public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
1375 public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
1376 public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
1377 public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
1378 public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
1379 public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1380 public int numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1381 public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1382 }
1383
1384
1385
1386 /***
1387 * The cap on the number of idle instances in the pool (per key).
1388 * @see #setMaxIdle
1389 * @see #getMaxIdle
1390 */
1391 private int _maxIdle = DEFAULT_MAX_IDLE;
1392
1393 /***
1394 * The minimum no of idle objects to keep in the pool (per key)
1395 * @see #setMinIdle
1396 * @see #getMinIdle
1397 */
1398 private int _minIdle = DEFAULT_MIN_IDLE;
1399
1400 /***
1401 * The cap on the number of active instances from the pool (per key).
1402 * @see #setMaxActive
1403 * @see #getMaxActive
1404 */
1405 private int _maxActive = DEFAULT_MAX_ACTIVE;
1406
1407 /***
1408 * The cap on the total number of instances from the pool if non-positive.
1409 * @see #setMaxTotal
1410 * @see #getMaxTotal
1411 */
1412 private int _maxTotal = DEFAULT_MAX_TOTAL;
1413
1414 /***
1415 * The maximum amount of time (in millis) the
1416 * {@link #borrowObject} method should block before throwing
1417 * an exception when the pool is exhausted and the
1418 * {@link #getWhenExhaustedAction "when exhausted" action} is
1419 * {@link #WHEN_EXHAUSTED_BLOCK}.
1420 *
1421 * When less than 0, the {@link #borrowObject} method
1422 * may block indefinitely.
1423 *
1424 * @see #setMaxWait
1425 * @see #getMaxWait
1426 * @see #WHEN_EXHAUSTED_BLOCK
1427 * @see #setWhenExhaustedAction
1428 * @see #getWhenExhaustedAction
1429 */
1430 private long _maxWait = DEFAULT_MAX_WAIT;
1431
1432 /***
1433 * The action to take when the {@link #borrowObject} method
1434 * is invoked when the pool is exhausted (the maximum number
1435 * of "active" objects has been reached).
1436 *
1437 * @see #WHEN_EXHAUSTED_BLOCK
1438 * @see #WHEN_EXHAUSTED_FAIL
1439 * @see #WHEN_EXHAUSTED_GROW
1440 * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
1441 * @see #setWhenExhaustedAction
1442 * @see #getWhenExhaustedAction
1443 */
1444 private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
1445
1446 /***
1447 * When <tt>true</tt>, objects will be
1448 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1449 * before being returned by the {@link #borrowObject}
1450 * method. If the object fails to validate,
1451 * it will be dropped from the pool, and we will attempt
1452 * to borrow another.
1453 *
1454 * @see #setTestOnBorrow
1455 * @see #getTestOnBorrow
1456 */
1457 private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
1458
1459 /***
1460 * When <tt>true</tt>, objects will be
1461 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1462 * before being returned to the pool within the
1463 * {@link #returnObject}.
1464 *
1465 * @see #getTestOnReturn
1466 * @see #setTestOnReturn
1467 */
1468 private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
1469
1470 /***
1471 * When <tt>true</tt>, objects will be
1472 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1473 * by the idle object evictor (if any). If an object
1474 * fails to validate, it will be dropped from the pool.
1475 *
1476 * @see #setTestWhileIdle
1477 * @see #getTestWhileIdle
1478 * @see #getTimeBetweenEvictionRunsMillis
1479 * @see #setTimeBetweenEvictionRunsMillis
1480 */
1481 private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
1482
1483 /***
1484 * The number of milliseconds to sleep between runs of the
1485 * idle object evictor thread.
1486 * When non-positive, no idle object evictor thread will be
1487 * run.
1488 *
1489 * @see #setTimeBetweenEvictionRunsMillis
1490 * @see #getTimeBetweenEvictionRunsMillis
1491 */
1492 private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1493
1494 /***
1495 * The number of objects to examine during each run of the
1496 * idle object evictor thread (if any).
1497 * <p>
1498 * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
1499 * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
1500 * idle objects will be tested per run.
1501 *
1502 * @see #setNumTestsPerEvictionRun
1503 * @see #getNumTestsPerEvictionRun
1504 * @see #getTimeBetweenEvictionRunsMillis
1505 * @see #setTimeBetweenEvictionRunsMillis
1506 */
1507 private int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1508
1509 /***
1510 * The minimum amount of time an object may sit idle in the pool
1511 * before it is eligable for eviction by the idle object evictor
1512 * (if any).
1513 * When non-positive, no objects will be evicted from the pool
1514 * due to idle time alone.
1515 *
1516 * @see #setMinEvictableIdleTimeMillis
1517 * @see #getMinEvictableIdleTimeMillis
1518 * @see #getTimeBetweenEvictionRunsMillis
1519 * @see #setTimeBetweenEvictionRunsMillis
1520 */
1521 private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1522
1523 /*** My hash of pools (CursorableLinkedLists). */
1524 private HashMap _poolMap = null;
1525
1526 /*** Count of active objects, per key. */
1527 private HashMap _activeMap = null;
1528
1529 /*** The total number of active instances. */
1530 private int _totalActive = 0;
1531
1532 /*** The total number of idle instances. */
1533 private int _totalIdle = 0;
1534
1535 /*** My {@link KeyedPoolableObjectFactory}. */
1536 private KeyedPoolableObjectFactory _factory = null;
1537
1538 /***
1539 * My idle object eviction {@link TimerTask}, if any.
1540 */
1541 private Evictor _evictor = null;
1542
1543 /***
1544 * Idle object pool keys that have been evicted recently.
1545 */
1546 private Set _recentlyEvictedKeys = null;
1547
1548 /***
1549 * Position in the _pool where the _evictor last stopped.
1550 */
1551 private int _evictLastIndex = -1;
1552 }