Source code: org/apache/commons/pool/impl/GenericKeyedObjectPool.java
1 /*
2 * Copyright 1999-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.commons.pool.impl;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.NoSuchElementException;
22
23 import org.apache.commons.collections.CursorableLinkedList;
24 import org.apache.commons.pool.BaseKeyedObjectPool;
25 import org.apache.commons.pool.KeyedObjectPool;
26 import org.apache.commons.pool.KeyedPoolableObjectFactory;
27
28 /**
29 * A configurable {@link KeyedObjectPool} implementation.
30 * <p>
31 * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
32 * <tt>GenericKeyedObjectPool</tt> provides robust pooling functionality for
33 * arbitrary objects.
34 * <p>
35 * A <tt>GenericKeyedObjectPool</tt> provides a number of configurable parameters:
36 * <ul>
37 * <li>
38 * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects (per key)
39 * that can be borrowed from the pool at one time. When non-positive, there
40 * is no limit to the number of objects that may be active at one time.
41 * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
42 * </li>
43 * <li>
44 * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
45 * sit idle in the pool (per key) at any time. When negative, there
46 * is no limit to the number of objects that may be idle at one time.
47 * </li>
48 * <li>
49 * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
50 * behaviour of the {@link #borrowObject} method when the pool is exhausted:
51 * <ul>
52 * <li>
53 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
54 * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
55 * a {@link NoSuchElementException}
56 * </li>
57 * <li>
58 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
59 * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
60 * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
61 * meaningless.)
62 * </li>
63 * <li>
64 * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
65 * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
66 * (invoke {@link Object#wait} until a new or idle object is available.
67 * If a positive {@link #setMaxWait <i>maxWait</i>}
68 * value is supplied, the {@link #borrowObject} will block for at
69 * most that many milliseconds, after which a {@link NoSuchElementException}
70 * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive,
71 * the {@link #borrowObject} method will block indefinitely.
72 * </li>
73 * </ul>
74 * </li>
75 * <li>
76 * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
77 * attempt to validate each object before it is returned from the
78 * {@link #borrowObject} method. (Using the provided factory's
79 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject} method.) Objects that fail
80 * to validate will be dropped from the pool, and a different object will
81 * be borrowed.
82 * </li>
83 * <li>
84 * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
85 * attempt to validate each object before it is returned to the pool in the
86 * {@link #returnObject} method. (Using the provided factory's
87 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject}
88 * method.) Objects that fail to validate will be dropped from the pool.
89 * </li>
90 * </ul>
91 * <p>
92 * Optionally, one may configure the pool to examine and possibly evict objects as they
93 * sit idle in the pool. This is performed by an "idle object eviction" thread, which
94 * runs asychronously. The idle object eviction thread may be configured using the
95 * following attributes:
96 * <ul>
97 * <li>
98 * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
99 * indicates how long the eviction thread should sleep before "runs" of examining
100 * idle objects. When non-positive, no eviction thread will be launched.
101 * </li>
102 * <li>
103 * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
104 * specifies the minimum amount of time that an object may sit idle in the pool
105 * before it is eligable for eviction due to idle time. When non-positive, no object
106 * will be dropped from the pool due to idle time alone.
107 * </li>
108 * <li>
109 * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
110 * objects should be validated using the factory's
111 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject} method. Objects
112 * that fail to validate will be dropped from the pool.
113 * </li>
114 * </ul>
115 * <p>
116 * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}. A
117 * non-<code>null</code> factory must be provided either as a constructor argument
118 * or via a call to {@link #setFactory} before the pool is used.
119 * </p>
120 * @see GenericObjectPool
121 * @author Rodney Waldhoff
122 * @author Dirk Verbeeck
123 * @version $Revision: 1.26 $ $Date: 2004/02/28 11:46:33 $
124 */
125 public class GenericKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
126
127 //--- public constants -------------------------------------------
128
129 /**
130 * A "when exhausted action" type indicating that when the pool is
131 * exhausted (i.e., the maximum number of active objects has
132 * been reached), the {@link #borrowObject}
133 * method should fail, throwing a {@link NoSuchElementException}.
134 * @see #WHEN_EXHAUSTED_BLOCK
135 * @see #WHEN_EXHAUSTED_GROW
136 * @see #setWhenExhaustedAction
137 */
138 public static final byte WHEN_EXHAUSTED_FAIL = 0;
139
140 /**
141 * A "when exhausted action" type indicating that when the pool
142 * is exhausted (i.e., the maximum number
143 * of active objects has been reached), the {@link #borrowObject}
144 * method should block until a new object is available, or the
145 * {@link #getMaxWait maximum wait time} has been reached.
146 * @see #WHEN_EXHAUSTED_FAIL
147 * @see #WHEN_EXHAUSTED_GROW
148 * @see #setMaxWait
149 * @see #getMaxWait
150 * @see #setWhenExhaustedAction
151 */
152 public static final byte WHEN_EXHAUSTED_BLOCK = 1;
153
154 /**
155 * A "when exhausted action" type indicating that when the pool is
156 * exhausted (i.e., the maximum number
157 * of active objects has been reached), the {@link #borrowObject}
158 * method should simply create a new object anyway.
159 * @see #WHEN_EXHAUSTED_FAIL
160 * @see #WHEN_EXHAUSTED_GROW
161 * @see #setWhenExhaustedAction
162 */
163 public static final byte WHEN_EXHAUSTED_GROW = 2;
164
165 /**
166 * The default cap on the number of idle instances in the pool
167 * (per key).
168 * @see #getMaxIdle
169 * @see #setMaxIdle
170 */
171 public static final int DEFAULT_MAX_IDLE = 8;
172
173 /**
174 * The default cap on the total number of active instances from the pool
175 * (per key).
176 * @see #getMaxActive
177 * @see #setMaxActive
178 */
179 public static final int DEFAULT_MAX_ACTIVE = 8;
180
181 /**
182 * The default cap on the the maximum number of objects that can exists at one time.
183 * @see #getMaxTotal
184 * @see #setMaxTotal
185 */
186 public static final int DEFAULT_MAX_TOTAL = -1;
187
188 /**
189 * The default "when exhausted action" for the pool.
190 * @see #WHEN_EXHAUSTED_BLOCK
191 * @see #WHEN_EXHAUSTED_FAIL
192 * @see #WHEN_EXHAUSTED_GROW
193 * @see #setWhenExhaustedAction
194 */
195 public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
196
197 /**
198 * The default maximum amount of time (in millis) the
199 * {@link #borrowObject} method should block before throwing
200 * an exception when the pool is exhausted and the
201 * {@link #getWhenExhaustedAction "when exhausted" action} is
202 * {@link #WHEN_EXHAUSTED_BLOCK}.
203 * @see #getMaxWait
204 * @see #setMaxWait
205 */
206 public static final long DEFAULT_MAX_WAIT = -1L;
207
208 /**
209 * The default "test on borrow" value.
210 * @see #getTestOnBorrow
211 * @see #setTestOnBorrow
212 */
213 public static final boolean DEFAULT_TEST_ON_BORROW = false;
214
215 /**
216 * The default "test on return" value.
217 * @see #getTestOnReturn
218 * @see #setTestOnReturn
219 */
220 public static final boolean DEFAULT_TEST_ON_RETURN = false;
221
222 /**
223 * The default "test while idle" value.
224 * @see #getTestWhileIdle
225 * @see #setTestWhileIdle
226 * @see #getTimeBetweenEvictionRunsMillis
227 * @see #setTimeBetweenEvictionRunsMillis
228 */
229 public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
230
231 /**
232 * The default "time between eviction runs" value.
233 * @see #getTimeBetweenEvictionRunsMillis
234 * @see #setTimeBetweenEvictionRunsMillis
235 */
236 public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
237
238 /**
239 * The default number of objects to examine per run in the
240 * idle object evictor.
241 * @see #getNumTestsPerEvictionRun
242 * @see #setNumTestsPerEvictionRun
243 * @see #getTimeBetweenEvictionRunsMillis
244 * @see #setTimeBetweenEvictionRunsMillis
245 */
246 public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
247
248 /**
249 * The default value for {@link #getMinEvictableIdleTimeMillis}.
250 * @see #getMinEvictableIdleTimeMillis
251 * @see #setMinEvictableIdleTimeMillis
252 */
253 public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
254
255 //--- constructors -----------------------------------------------
256
257 /**
258 * Create a new <tt>GenericKeyedObjectPool</tt>..
259 */
260 public GenericKeyedObjectPool() {
261 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);
262 }
263
264 /**
265 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
266 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
267 */
268 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) {
269 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);
270 }
271
272 /**
273 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
274 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
275 * @param config a non-<tt>null</tt> {@link GenericKeyedObjectPool.Config} describing my configuration
276 */
277 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
278 this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
279 }
280
281 /**
282 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
283 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
284 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
285 */
286 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
287 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);
288 }
289
290 /**
291 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
292 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
293 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
294 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
295 * @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})
296 */
297 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
298 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);
299 }
300
301 /**
302 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
303 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
304 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
305 * @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})
306 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
307 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
308 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
309 */
310 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
311 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);
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 whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
319 * @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})
320 * @param maxIdle the maximum number of idle objects in my pool (per key) (see {@link #setMaxIdle})
321 */
322 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
323 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);
324 }
325
326 /**
327 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
328 * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
329 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
330 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
331 * @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})
332 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
333 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
334 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
335 */
336 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
337 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);
338 }
339
340 /**
341 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
342 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
343 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
344 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
345 * @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})
346 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
347 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
348 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
349 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
350 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
351 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
352 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
353 */
354 public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
355 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
356 }
357
358 /**
359 * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
360 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
361 * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
362 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
363 * @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})
364 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
365 * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
366 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
367 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
368 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
369 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
370 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
371 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
372 */
373 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) {
374 _factory = factory;
375 _maxActive = maxActive;
376 switch(whenExhaustedAction) {
377 case WHEN_EXHAUSTED_BLOCK:
378 case WHEN_EXHAUSTED_FAIL:
379 case WHEN_EXHAUSTED_GROW:
380 _whenExhaustedAction = whenExhaustedAction;
381 break;
382 default:
383 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
384 }
385 _maxWait = maxWait;
386 _maxIdle = maxIdle;
387 _maxTotal = maxTotal;
388 _testOnBorrow = testOnBorrow;
389 _testOnReturn = testOnReturn;
390 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
391 _numTestsPerEvictionRun = numTestsPerEvictionRun;
392 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
393 _testWhileIdle = testWhileIdle;
394
395 _poolMap = new HashMap();
396 _activeMap = new HashMap();
397 _poolList = new CursorableLinkedList();
398
399 startEvictor(_timeBetweenEvictionRunsMillis);
400 }
401
402 //--- public methods ---------------------------------------------
403
404 //--- configuration methods --------------------------------------
405
406 /**
407 * Returns the cap on the number of active instances from my pool (per key).
408 * @return the cap on the number of active instances from my pool (per key).
409 * @see #setMaxActive
410 */
411 public synchronized int getMaxActive() {
412 return _maxActive;
413 }
414
415 /**
416 * Sets the cap on the number of active instances from my pool (per key).
417 * @param maxActive The cap on the number of active instances from my pool (per key).
418 * Use a negative value for an infinite number of instances.
419 * @see #getMaxActive
420 */
421 public synchronized void setMaxActive(int maxActive) {
422 _maxActive = maxActive;
423 notifyAll();
424 }
425
426 /**
427 * Returns the cap on the total number of instances from my pool.
428 * @return the cap on the total number of instances from my pool.
429 * @see #setMaxTotal
430 */
431 public synchronized int getMaxTotal() {
432 return _maxTotal;
433 }
434
435 /**
436 * Sets the cap on the total number of instances from my pool.
437 * @param maxTotal The cap on the total number of instances from my pool.
438 * Use a negative value for an infinite number of instances.
439 * @see #getMaxTotal
440 */
441 public synchronized void setMaxTotal(int maxTotal) {
442 _maxTotal = maxTotal;
443 notifyAll();
444 }
445
446 /**
447 * Returns the action to take when the {@link #borrowObject} method
448 * is invoked when the pool is exhausted (the maximum number
449 * of "active" objects has been reached).
450 *
451 * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
452 * @see #setWhenExhaustedAction
453 */
454 public synchronized byte getWhenExhaustedAction() {
455 return _whenExhaustedAction;
456 }
457
458 /**
459 * Sets the action to take when the {@link #borrowObject} method
460 * is invoked when the pool is exhausted (the maximum number
461 * of "active" objects has been reached).
462 *
463 * @param whenExhaustedAction the action code, which must be one of
464 * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
465 * or {@link #WHEN_EXHAUSTED_GROW}
466 * @see #getWhenExhaustedAction
467 */
468 public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
469 switch(whenExhaustedAction) {
470 case WHEN_EXHAUSTED_BLOCK:
471 case WHEN_EXHAUSTED_FAIL:
472 case WHEN_EXHAUSTED_GROW:
473 _whenExhaustedAction = whenExhaustedAction;
474 notifyAll();
475 break;
476 default:
477 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
478 }
479 }
480
481
482 /**
483 * Returns the maximum amount of time (in milliseconds) the
484 * {@link #borrowObject} method should block before throwing
485 * an exception when the pool is exhausted and the
486 * {@link #setWhenExhaustedAction "when exhausted" action} is
487 * {@link #WHEN_EXHAUSTED_BLOCK}.
488 *
489 * When less than 0, the {@link #borrowObject} method
490 * may block indefinitely.
491 *
492 * @see #setMaxWait
493 * @see #setWhenExhaustedAction
494 * @see #WHEN_EXHAUSTED_BLOCK
495 */
496 public synchronized long getMaxWait() {
497 return _maxWait;
498 }
499
500 /**
501 * Sets the maximum amount of time (in milliseconds) the
502 * {@link #borrowObject} method should block before throwing
503 * an exception when the pool is exhausted and the
504 * {@link #setWhenExhaustedAction "when exhausted" action} is
505 * {@link #WHEN_EXHAUSTED_BLOCK}.
506 *
507 * When less than 0, the {@link #borrowObject} method
508 * may block indefinitely.
509 *
510 * @see #getMaxWait
511 * @see #setWhenExhaustedAction
512 * @see #WHEN_EXHAUSTED_BLOCK
513 */
514 public synchronized void setMaxWait(long maxWait) {
515 _maxWait = maxWait;
516 }
517
518 /**
519 * Returns the cap on the number of "idle" instances in the pool.
520 * @return the cap on the number of "idle" instances in the pool.
521 * @see #setMaxIdle
522 */
523 public synchronized int getMaxIdle() {
524 return _maxIdle;
525 }
526
527 /**
528 * Sets the cap on the number of "idle" instances in the pool.
529 * @param maxIdle The cap on the number of "idle" instances in the pool.
530 * Use a negative value to indicate an unlimited number
531 * of idle instances.
532 * @see #getMaxIdle
533 */
534 public synchronized void setMaxIdle(int maxIdle) {
535 _maxIdle = maxIdle;
536 notifyAll();
537 }
538
539 /**
540 * When <tt>true</tt>, objects will be
541 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
542 * before being returned by the {@link #borrowObject}
543 * method. If the object fails to validate,
544 * it will be dropped from the pool, and we will attempt
545 * to borrow another.
546 *
547 * @see #setTestOnBorrow
548 */
549 public synchronized boolean getTestOnBorrow() {
550 return _testOnBorrow;
551 }
552
553 /**
554 * When <tt>true</tt>, objects will be
555 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
556 * before being returned by the {@link #borrowObject}
557 * method. If the object fails to validate,
558 * it will be dropped from the pool, and we will attempt
559 * to borrow another.
560 *
561 * @see #getTestOnBorrow
562 */
563 public synchronized void setTestOnBorrow(boolean testOnBorrow) {
564 _testOnBorrow = testOnBorrow;
565 }
566
567 /**
568 * When <tt>true</tt>, objects will be
569 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
570 * before being returned to the pool within the
571 * {@link #returnObject}.
572 *
573 * @see #setTestOnReturn
574 */
575 public synchronized boolean getTestOnReturn() {
576 return _testOnReturn;
577 }
578
579 /**
580 * When <tt>true</tt>, objects will be
581 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
582 * before being returned to the pool within the
583 * {@link #returnObject}.
584 *
585 * @see #getTestOnReturn
586 */
587 public synchronized void setTestOnReturn(boolean testOnReturn) {
588 _testOnReturn = testOnReturn;
589 }
590
591 /**
592 * Returns the number of milliseconds to sleep between runs of the
593 * idle object evictor thread.
594 * When non-positive, no idle object evictor thread will be
595 * run.
596 *
597 * @see #setTimeBetweenEvictionRunsMillis
598 */
599 public synchronized long getTimeBetweenEvictionRunsMillis() {
600 return _timeBetweenEvictionRunsMillis;
601 }
602
603 /**
604 * Sets the number of milliseconds to sleep between runs of the
605 * idle object evictor thread.
606 * When non-positive, no idle object evictor thread will be
607 * run.
608 *
609 * @see #getTimeBetweenEvictionRunsMillis
610 */
611 public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
612 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
613 startEvictor(_timeBetweenEvictionRunsMillis);
614 }
615
616 /**
617 * Returns the number of objects to examine during each run of the
618 * idle object evictor thread (if any).
619 *
620 * @see #setNumTestsPerEvictionRun
621 * @see #setTimeBetweenEvictionRunsMillis
622 */
623 public synchronized int getNumTestsPerEvictionRun() {
624 return _numTestsPerEvictionRun;
625 }
626
627 /**
628 * Sets the number of objects to examine during each run of the
629 * idle object evictor thread (if any).
630 * <p>
631 * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
632 * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
633 * idle objects will be tested per run.
634 *
635 * @see #getNumTestsPerEvictionRun
636 * @see #setTimeBetweenEvictionRunsMillis
637 */
638 public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
639 _numTestsPerEvictionRun = numTestsPerEvictionRun;
640 }
641
642 /**
643 * Returns the minimum amount of time an object may sit idle in the pool
644 * before it is eligable for eviction by the idle object evictor
645 * (if any).
646 *
647 * @see #setMinEvictableIdleTimeMillis
648 * @see #setTimeBetweenEvictionRunsMillis
649 */
650 public synchronized long getMinEvictableIdleTimeMillis() {
651 return _minEvictableIdleTimeMillis;
652 }
653
654 /**
655 * Sets the minimum amount of time an object may sit idle in the pool
656 * before it is eligable for eviction by the idle object evictor
657 * (if any).
658 * When non-positive, no objects will be evicted from the pool
659 * due to idle time alone.
660 *
661 * @see #getMinEvictableIdleTimeMillis
662 * @see #setTimeBetweenEvictionRunsMillis
663 */
664 public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
665 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
666 }
667
668 /**
669 * When <tt>true</tt>, objects will be
670 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
671 * by the idle object evictor (if any). If an object
672 * fails to validate, it will be dropped from the pool.
673 *
674 * @see #setTestWhileIdle
675 * @see #setTimeBetweenEvictionRunsMillis
676 */
677 public synchronized boolean getTestWhileIdle() {
678 return _testWhileIdle;
679 }
680
681 /**
682 * When <tt>true</tt>, objects will be
683 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
684 * by the idle object evictor (if any). If an object
685 * fails to validate, it will be dropped from the pool.
686 *
687 * @see #getTestWhileIdle
688 * @see #setTimeBetweenEvictionRunsMillis
689 */
690 public synchronized void setTestWhileIdle(boolean testWhileIdle) {
691 _testWhileIdle = testWhileIdle;
692 }
693
694 /**
695 * Sets my configuration.
696 * @see GenericKeyedObjectPool.Config
697 */
698 public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
699 setMaxIdle(conf.maxIdle);
700 setMaxActive(conf.maxActive);
701 setMaxTotal(conf.maxTotal);
702 setMaxWait(conf.maxWait);
703 setWhenExhaustedAction(conf.whenExhaustedAction);
704 setTestOnBorrow(conf.testOnBorrow);
705 setTestOnReturn(conf.testOnReturn);
706 setTestWhileIdle(conf.testWhileIdle);
707 setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
708 setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
709 setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
710 }
711
712 //-- ObjectPool methods ------------------------------------------
713
714 public synchronized Object borrowObject(Object key) throws Exception {
715 long starttime = System.currentTimeMillis();
716 boolean newlyCreated = false;
717 for(;;) {
718 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
719 if(null == pool) {
720 pool = new CursorableLinkedList();
721 _poolMap.put(key,pool);
722 _poolList.add(key);
723 }
724 ObjectTimestampPair pair = null;
725 // if there are any sleeping, just grab one of those
726 try {
727 pair = (ObjectTimestampPair)(pool.removeFirst());
728 if(null != pair) {
729 _totalIdle--;
730 }
731 } catch(NoSuchElementException e) { /* ignored */
732 }
733 // otherwise
734 if(null == pair) {
735 // if there is a totalMaxActive and we are at the limit then
736 // we have to make room
737 // TODO: this could be improved by only removing the oldest object
738 if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
739 clear();
740 }
741
742 // check if we can create one
743 // (note we know that the num sleeping is 0, else we wouldn't be here)
744 int active = getActiveCount(key);
745 if ((_maxActive <= 0 || active < _maxActive) &&
746 (_maxTotal <= 0 || _totalActive + _totalIdle < _maxTotal)) {
747 Object obj = _factory.makeObject(key);
748 pair = new ObjectTimestampPair(obj);
749 newlyCreated = true;
750 } else {
751 // the pool is exhausted
752 switch(_whenExhaustedAction) {
753 case WHEN_EXHAUSTED_GROW:
754 Object obj = _factory.makeObject(key);
755 pair = new ObjectTimestampPair(obj);
756 break;
757 case WHEN_EXHAUSTED_FAIL:
758 throw new NoSuchElementException();
759 case WHEN_EXHAUSTED_BLOCK:
760 try {
761 if(_maxWait <= 0) {
762 wait();
763 } else {
764 wait(_maxWait);
765 }
766 } catch(InterruptedException e) {
767 // ignored
768 }
769 if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
770 throw new NoSuchElementException("Timeout waiting for idle object");
771 } else {
772 continue; // keep looping
773 }
774 default:
775 throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
776 }
777 }
778 }
779 _factory.activateObject(key,pair.value);
780 if(_testOnBorrow && !_factory.validateObject(key,pair.value)) {
781 _factory.destroyObject(key,pair.value);
782 if(newlyCreated) {
783 throw new NoSuchElementException("Could not create a validated object");
784 } // else keep looping
785 } else {
786 incrementActiveCount(key);
787 return pair.value;
788 }
789 }
790 }
791
792 public synchronized void clear() {
793 for(Iterator keyiter = _poolList.iterator(); keyiter.hasNext(); ) {
794 Object key = keyiter.next();
795 CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key));
796 for(Iterator it = list.iterator(); it.hasNext(); ) {
797 try {
798 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
799 } catch(Exception e) {
800 // ignore error, keep destroying the rest
801 }
802 it.remove();
803 }
804 }
805 _poolMap.clear();
806 _poolList.clear();
807 _totalIdle = 0;
808 notifyAll();
809 }
810
811 public synchronized void clear(Object key) {
812 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key));
813 if(null == pool) {
814 return;
815 } else {
816 _poolList.remove(key);
817 for(Iterator it = pool.iterator(); it.hasNext(); ) {
818 try {
819 _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
820 } catch(Exception e) {
821 // ignore error, keep destroying the rest
822 }
823 it.remove();
824 _totalIdle--;
825 }
826 }
827 notifyAll();
828 }
829
830 public synchronized int getNumActive() {
831 return _totalActive;
832 }
833
834 public synchronized int getNumIdle() {
835 return _totalIdle;
836 }
837
838 public synchronized int getNumActive(Object key) {
839 return getActiveCount(key);
840 }
841
842 public synchronized int getNumIdle(Object key) {
843 try {
844 return((CursorableLinkedList)(_poolMap.get(key))).size();
845 } catch(Exception e) {
846 return 0;
847 }
848 }
849
850 public void returnObject(Object key, Object obj) throws Exception {
851
852 // if we need to validate this object, do so
853 boolean success = true; // whether or not this object passed validation
854 if(_testOnReturn && !_factory.validateObject(key, obj)) {
855 success = false;
856 try {
857 _factory.destroyObject(key, obj);
858 } catch(Exception e) {
859 // ignored
860 }
861 } else {
862 try {
863 _factory.passivateObject(key, obj);
864 } catch(Exception e) {
865 success = false;
866 }
867 }
868
869 boolean shouldDestroy = false;
870 synchronized(this) {
871 // grab the pool (list) of objects associated with the given key
872 CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get(key));
873 // if it doesn't exist, create it
874 if(null == pool) {
875 pool = new CursorableLinkedList();
876 _poolMap.put(key, pool);
877 _poolList.add(key);
878 }
879 decrementActiveCount(key);
880 // if there's no space in the pool, flag the object for destruction
881 // else if we passivated succesfully, return it to the pool
882 if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
883 shouldDestroy = true;
884 } else if(success) {
885 pool.addFirst(new ObjectTimestampPair(obj));
886 _totalIdle++;
887 }
888 notifyAll();
889 }
890
891 if(shouldDestroy) {
892 try {
893 _factory.destroyObject(key, obj);
894 } catch(Exception e) {
895 // ignored?
896 }
897 }
898 }
899
900 public void invalidateObject(Object key, Object obj) throws Exception {
901 try {
902 _factory.destroyObject(key, obj);
903 }
904 finally {
905 synchronized(this) {
906 decrementActiveCount(key);
907 notifyAll(); // _totalActive has changed
908 }
909 }
910 }
911
912 public void addObject(Object key) throws Exception {
913 Object obj = _factory.makeObject(key);
914 synchronized(this) {
915 incrementActiveCount(key); // returnObject will decrement this
916 returnObject(key,obj);
917 }
918 }
919
920 public synchronized void close() throws Exception {
921 clear();
922 _poolList = null;
923 _poolMap = null;
924 _activeMap = null;
925 if(null != _evictionCursor) {
926 _evictionCursor.close();
927 _evictionCursor = null;
928 }
929 if(null != _evictionKeyCursor) {
930 _evictionKeyCursor.close();
931 _evictionKeyCursor = null;
932 }
933 if(null != _evictor) {
934 _evictor.cancel();
935 _evictor = null;
936 }
937 }
938
939 public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
940 if(0 < getNumActive()) {
941 throw new IllegalStateException("Objects are already active");
942 } else {
943 clear();
944 _factory = factory;
945 }
946 }
947
948 public synchronized void evict() throws Exception {
949 Object key = null;
950 for(int i=0,m=getNumTests();i<m;i++) {
951 if(_poolMap.size() > 0) {
952 // if we don't have a key cursor, then create one, and close any object cursor
953 if(null == _evictionKeyCursor) {
954 _evictionKeyCursor = _poolList.cursor();
955 key = null;
956 if(null != _evictionCursor) {
957 _evictionCursor.close();
958 _evictionCursor = null;
959 }
960 }
961 // if we don't have an object cursor
962 if(null == _evictionCursor) {
963 // if the _evictionKeyCursor has a next value, then use it
964 if(_evictionKeyCursor.hasNext()) {
965 key = _evictionKeyCursor.next();
966 CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
967 _evictionCursor = pool.cursor(pool.size());
968 } else {
969 // else close the key cursor and loop back around
970 if(null != _evictionKeyCursor) {
971 _evictionKeyCursor.close();
972 _evictionKeyCursor = _poolList.cursor();
973 if(null != _evictionCursor) {
974 _evictionCursor.close();
975 _evictionCursor = null;
976 }
977 }
978 continue;
979 }
980 }
981 // if the _evictionCursor has a previous object, then test it
982 if(_evictionCursor.hasPrevious()) {
983 ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
984 boolean removeObject=false;
985 if(_minEvictableIdleTimeMillis > 0 &&
986 System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
987 removeObject=true;
988 } else if(_testWhileIdle) {
989 boolean active = false;
990 try {
991 _factory.activateObject(key,pair.value);
992 active = true;
993 } catch(Exception e) {
994 removeObject=true;
995 }
996 if(active) {
997 if(!_factory.validateObject(key,pair.value)) {
998 removeObject=true;
999 } else {
1000 try {
1001 _factory.passivateObject(key,pair.value);
1002 } catch(Exception e) {
1003 removeObject=true;
1004 }
1005 }
1006 }
1007 }
1008 if(removeObject) {
1009 try {
1010 _evictionCursor.remove();
1011 _totalIdle--;
1012 _factory.destroyObject(key,pair.value);
1013
1014 // if that was the last object for that key, drop that pool
1015 if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
1016 _poolMap.remove(key);
1017 _poolList.remove(key);
1018 }
1019 } catch(Exception e) {
1020 ; // ignored
1021 }
1022 }
1023 } else {
1024 // else the _evictionCursor is done, so close it and loop around
1025 if(_evictionCursor != null) {
1026 _evictionCursor.close();
1027 _evictionCursor = null;
1028 }
1029 }
1030 }
1031 }
1032 }
1033
1034 //--- non-public methods ----------------------------------------
1035
1036 /**
1037 * Start the eviction thread or service, or when
1038 * <i>delay</i> is non-positive, stop it
1039 * if it is already running.
1040 */
1041 protected synchronized void startEvictor(long delay) {
1042 if(null != _evictor) {
1043 _evictor.cancel();
1044 _evictor = null;
1045 }
1046 if(delay > 0) {
1047 _evictor = new Evictor(delay);
1048 Thread t = new Thread(_evictor);
1049 t.setDaemon(true);
1050 t.start();
1051 }
1052 }
1053
1054 synchronized String debugInfo() {
1055 StringBuffer buf = new StringBuffer();
1056 buf.append("Active: ").append(getNumActive()).append("\n");
1057 buf.append("Idle: ").append(getNumIdle()).append("\n");
1058 Iterator it = _poolList.iterator();
1059 while(it.hasNext()) {
1060 buf.append("\t").append(_poolMap.get(it.next())).append("\n");
1061 }
1062 return buf.toString();
1063 }
1064
1065 private synchronized int getNumTests() {
1066 if(_numTestsPerEvictionRun >= 0) {
1067 return _numTestsPerEvictionRun;
1068 } else {
1069 return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
1070 }
1071 }
1072
1073 private synchronized void incrementActiveCount(Object key) {
1074 _totalActive++;
1075 Integer active = (Integer)(_activeMap.get(key));
1076 if(null == active) {
1077 _activeMap.put(key,new Integer(1));
1078 } else {
1079 _activeMap.put(key,new Integer(active.intValue() + 1));
1080 }
1081 }
1082
1083 private synchronized void decrementActiveCount(Object key) {
1084 _totalActive--;
1085 Integer active = (Integer)(_activeMap.get(key));
1086 if(null == active) {
1087 // do nothing, either null or zero is OK
1088 } else if(active.intValue() <= 1) {
1089 _activeMap.remove(key);
1090 } else {
1091 _activeMap.put(key, new Integer(active.intValue() - 1));
1092 }
1093 }
1094
1095 private synchronized int getActiveCount(Object key) {
1096 int active = 0;
1097 Integer act = (Integer)(_activeMap.get(key));
1098 if(null != act) {
1099 active = act.intValue();
1100 }
1101 return active;
1102 }
1103
1104 //--- inner classes ----------------------------------------------
1105
1106 /**
1107 * A simple "struct" encapsulating an object instance and a timestamp.
1108 */
1109 class ObjectTimestampPair {
1110 Object value;
1111 long tstamp;
1112
1113 ObjectTimestampPair(Object val) {
1114 value = val;
1115 tstamp = System.currentTimeMillis();
1116 }
1117
1118 ObjectTimestampPair(Object val, long time) {
1119 value = val;
1120 tstamp = time;
1121 }
1122
1123 public String toString() {
1124 return value + ";" + tstamp;
1125 }
1126 }
1127
1128 /**
1129 * The idle object evictor thread.
1130 * @see #setTimeBetweenEvictionRunsMillis
1131 */
1132 class Evictor implements Runnable {
1133 private boolean _cancelled = false;
1134 private long _delay = 0L;
1135
1136 public Evictor(long delay) {
1137 _delay = delay;
1138 }
1139
1140 void cancel() {
1141 _cancelled = true;
1142 }
1143
1144 public void run() {
1145 while(!_cancelled) {
1146 long sleeptime = 0L;
1147 synchronized(GenericKeyedObjectPool.this) {
1148 sleeptime = _timeBetweenEvictionRunsMillis;
1149 }
1150 try {
1151 Thread.sleep(sleeptime);
1152 } catch(Exception e) {
1153 ; // ignored
1154 }
1155 try {
1156 evict();
1157 } catch(Exception e) {
1158 ; // ignored
1159 }
1160 }
1161 synchronized(GenericKeyedObjectPool.this) {
1162 if(null != _evictionCursor) {
1163 _evictionCursor.close();
1164 _evictionCursor = null;
1165 }
1166 if(null != _evictionKeyCursor) {
1167 _evictionKeyCursor.close();
1168 _evictionKeyCursor = null;
1169 }
1170 }
1171 }
1172 }
1173
1174 /**
1175 * A simple "struct" encapsulating the
1176 * configuration information for a {@link GenericKeyedObjectPool}.
1177 * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
1178 * @see GenericKeyedObjectPool#setConfig
1179 */
1180 public static class Config {
1181 public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
1182 public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
1183 public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
1184 public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
1185 public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
1186 public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
1187 public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
1188 public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
1189 public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1190 public int numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1191 public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1192 }
1193
1194 //--- protected attributes ---------------------------------------
1195
1196 /**
1197 * The cap on the number of idle instances in the pool (per key).
1198 * @see #setMaxIdle
1199 * @see #getMaxIdle
1200 */
1201 private int _maxIdle = DEFAULT_MAX_IDLE;
1202
1203 /**
1204 * The cap on the number of active instances from the pool (per key).
1205 * @see #setMaxActive
1206 * @see #getMaxActive
1207 */
1208 private int _maxActive = DEFAULT_MAX_ACTIVE;
1209
1210 /**
1211 * The cap on the total number of instances from the pool.
1212 * @see #setMaxTotal
1213 * @see #getMaxTotal
1214 */
1215 private int _maxTotal = DEFAULT_MAX_TOTAL;
1216
1217 /**
1218 * The maximum amount of time (in millis) the
1219 * {@link #borrowObject} method should block before throwing
1220 * an exception when the pool is exhausted and the
1221 * {@link #getWhenExhaustedAction "when exhausted" action} is
1222 * {@link #WHEN_EXHAUSTED_BLOCK}.
1223 *
1224 * When less than 0, the {@link #borrowObject} method
1225 * may block indefinitely.
1226 *
1227 * @see #setMaxWait
1228 * @see #getMaxWait
1229 * @see #WHEN_EXHAUSTED_BLOCK
1230 * @see #setWhenExhaustedAction
1231 * @see #getWhenExhaustedAction
1232 */
1233 private long _maxWait = DEFAULT_MAX_WAIT;
1234
1235 /**
1236 * The action to take when the {@link #borrowObject} method
1237 * is invoked when the pool is exhausted (the maximum number
1238 * of "active" objects has been reached).
1239 *
1240 * @see #WHEN_EXHAUSTED_BLOCK
1241 * @see #WHEN_EXHAUSTED_FAIL
1242 * @see #WHEN_EXHAUSTED_GROW
1243 * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
1244 * @see #setWhenExhaustedAction
1245 * @see #getWhenExhaustedAction
1246 */
1247 private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
1248
1249 /**
1250 * When <tt>true</tt>, objects will be
1251 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1252 * before being returned by the {@link #borrowObject}
1253 * method. If the object fails to validate,
1254 * it will be dropped from the pool, and we will attempt
1255 * to borrow another.
1256 *
1257 * @see #setTestOnBorrow
1258 * @see #getTestOnBorrow
1259 */
1260 private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
1261
1262 /**
1263 * When <tt>true</tt>, objects will be
1264 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1265 * before being returned to the pool within the
1266 * {@link #returnObject}.
1267 *
1268 * @see #getTestOnReturn
1269 * @see #setTestOnReturn
1270 */
1271 private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
1272
1273 /**
1274 * When <tt>true</tt>, objects will be
1275 * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1276 * by the idle object evictor (if any). If an object
1277 * fails to validate, it will be dropped from the pool.
1278 *
1279 * @see #setTestWhileIdle
1280 * @see #getTestWhileIdle
1281 * @see #getTimeBetweenEvictionRunsMillis
1282 * @see #setTimeBetweenEvictionRunsMillis
1283 */
1284 private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
1285
1286 /**
1287 * The number of milliseconds to sleep between runs of the
1288 * idle object evictor thread.
1289 * When non-positive, no idle object evictor thread will be
1290 * run.
1291 *
1292 * @see #setTimeBetweenEvictionRunsMillis
1293 * @see #getTimeBetweenEvictionRunsMillis
1294 */
1295 private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1296
1297 /**
1298 * The number of objects to examine during each run of the
1299 * idle object evictor thread (if any).
1300 * <p>
1301 * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
1302 * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
1303 * idle objects will be tested per run.
1304 *
1305 * @see #setNumTestsPerEvictionRun
1306 * @see #getNumTestsPerEvictionRun
1307 * @see #getTimeBetweenEvictionRunsMillis
1308 * @see #setTimeBetweenEvictionRunsMillis
1309 */
1310 private int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1311
1312 /**
1313 * The minimum amount of time an object may sit idle in the pool
1314 * before it is eligable for eviction by the idle object evictor
1315 * (if any).
1316 * When non-positive, no objects will be evicted from the pool
1317 * due to idle time alone.
1318 *
1319 * @see #setMinEvictableIdleTimeMillis
1320 * @see #getMinEvictableIdleTimeMillis
1321 * @see #getTimeBetweenEvictionRunsMillis
1322 * @se