1
2
3
4
5
6
7
8
9
10 package org.apache.commons.pool.impl;
11
12 import java.util.Collections;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.NoSuchElementException;
16
17 import org.apache.commons.pool.PoolableObjectFactory;
18 import org.apache.commons.pool.impl.GenericKeyedObjectPool.ObjectTimestampPair;
19
20 /***
21 * Version of GenericObjectPool which is 'fair' with respect to the client
22 * threads using {@link #borrowObject <i>borrowObject</i>}. Those which enter
23 * first will receive objects from the pool first.
24 *
25 *
26 * @see GenericObjectPool
27 * @author Gordon Mohr
28 * @version $Revision: 4672 $ $Date: 2006-09-27 00:03:16 +0000 (Wed, 27 Sep 2006) $
29 */
30 @SuppressWarnings("unchecked")
31 public class FairGenericObjectPool extends GenericObjectPool {
32
33
34
35
36
37 /***
38 * Create a new <tt>FairGenericObjectPool</tt>.
39 */
40 public FairGenericObjectPool() {
41 this(null,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_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);
42 }
43
44 /***
45 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
46 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
47 */
48 public FairGenericObjectPool(PoolableObjectFactory factory) {
49 this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_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);
50 }
51
52 /***
53 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
54 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
55 * @param config a non-<tt>null</tt> {@link GenericObjectPool.Config} describing my configuration
56 */
57 public FairGenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) {
58 this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
59 }
60
61 /***
62 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
63 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
64 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
65 */
66 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive) {
67 this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_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);
68 }
69
70 /***
71 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
72 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
73 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
74 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
75 * @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})
76 */
77 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
78 this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_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);
79 }
80
81 /***
82 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
83 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
84 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
85 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
86 * @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})
87 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
88 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
89 */
90 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
91 this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_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);
92 }
93
94 /***
95 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
96 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
97 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
98 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
99 * @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})
100 * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
101 */
102 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
103 this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_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);
104 }
105
106 /***
107 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
108 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
109 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
110 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
111 * @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})
112 * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
113 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
114 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
115 */
116 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
117 this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_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);
118 }
119
120 /***
121 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
122 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
123 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
124 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
125 * @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})
126 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
127 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
128 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
129 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
130 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
131 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
132 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
133 */
134 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
135 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
136 }
137
138 /***
139 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
140 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
141 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
142 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
143 * @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})
144 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
145 * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
146 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
147 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
148 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
149 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
150 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
151 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
152 */
153 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
154 this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
155 }
156
157 /***
158 * Create a new <tt>FairGenericObjectPool</tt> using the specified values.
159 * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
160 * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
161 * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
162 * @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})
163 * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
164 * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
165 * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
166 * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
167 * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
168 * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
169 * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
170 * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
171 * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition with the extra condition that at least "minIdle" amount of object remain in the pool. (see {@link #setSoftMinEvictableIdleTimeMillis})
172 */
173 public FairGenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) {
174 super(factory, maxActive, whenExhaustedAction, maxWait, maxIdle,
175 minIdle, testOnBorrow, testOnReturn,
176 timeBetweenEvictionRunsMillis, numTestsPerEvictionRun,
177 minEvictableIdleTimeMillis, testWhileIdle,
178 softMinEvictableIdleTimeMillis);
179 _borrowerQueue = Collections.synchronizedList(new LinkedList());
180 }
181
182
183
184 /***
185 *
186 * @see org.apache.commons.pool.ObjectPool#borrowObject()
187 */
188 public Object borrowObject() throws Exception {
189 assertOpen();
190 long starttime = System.currentTimeMillis();
191
192
193
194 try {
195 synchronized(this) {
196
197 _borrowerQueue.add(Thread.currentThread());
198
199 for(;;) {
200 ObjectTimestampPair pair = null;
201
202
203
204 boolean eligible = _borrowerQueue.get(0)==Thread.currentThread();
205 if(eligible) {
206
207 try {
208 pair = (ObjectTimestampPair)(_pool.removeFirst());
209 } catch(NoSuchElementException e) {
210 ;
211 }
212 }
213
214
215 if(null == pair) {
216
217
218 if(eligible && (_maxActive < 0 || _numActive < _maxActive)) {
219
220 } else {
221
222
223 switch(_whenExhaustedAction) {
224 case WHEN_EXHAUSTED_GROW:
225
226 break;
227 case WHEN_EXHAUSTED_FAIL:
228 throw new NoSuchElementException("Pool exhausted");
229 case WHEN_EXHAUSTED_BLOCK:
230 try {
231 if(_maxWait <= 0) {
232 wait();
233 } else {
234
235
236 final long elapsed = (System.currentTimeMillis() - starttime);
237 final long waitTime = _maxWait - elapsed;
238 if (waitTime > 0)
239 {
240 wait(waitTime);
241 }
242 }
243 } catch(InterruptedException e) {
244
245 }
246 if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
247 throw new NoSuchElementException("Timeout waiting for idle object");
248 } else {
249 continue;
250 }
251 default:
252 throw new IllegalArgumentException("WhenExhaustedAction property " + _whenExhaustedAction + " not recognized.");
253 }
254 }
255 }
256 _numActive++;
257
258
259 boolean newlyCreated = false;
260 if(null == pair) {
261 try {
262 Object obj = _factory.makeObject();
263 pair = new ObjectTimestampPair(obj);
264 newlyCreated = true;
265 return pair.value;
266 } finally {
267 if (!newlyCreated) {
268
269 _numActive--;
270 notifyAll();
271 }
272 }
273 }
274
275
276 try {
277 _factory.activateObject(pair.value);
278 if(_testOnBorrow && !_factory.validateObject(pair.value)) {
279 throw new Exception("ValidateObject failed");
280 }
281 return pair.value;
282 }
283 catch (Throwable e) {
284
285 _numActive--;
286 notifyAll();
287 try {
288 _factory.destroyObject(pair.value);
289 }
290 catch (Throwable e2) {
291
292 }
293 if(newlyCreated) {
294 throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
295 }
296 else {
297 continue;
298 }
299 }
300 }
301 }
302 } finally {
303
304 _borrowerQueue.remove(Thread.currentThread());
305 }
306 }
307
308 /*** Waiting borrowers (threads in #borrowObject ) */
309 protected List _borrowerQueue;
310 }