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