KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > pool > impl > FairGenericObjectPool


1 /* FairGenericObjectPool
2 *
3 * $Id: FairGenericObjectPool.java,v 1.2.6.1 2007/01/13 01:31:05 stack-sf Exp $
4 *
5 * Created on Apr 7, 2006
6 *
7 * Copyright (C) 2006 Internet Archive.
8 */

9
10 package org.apache.commons.pool.impl;
11
12 import java.util.Collections JavaDoc;
13 import java.util.LinkedList JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.NoSuchElementException JavaDoc;
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: 1.2.6.1 $ $Date: 2007/01/13 01:31:05 $
29  */

30 @SuppressWarnings JavaDoc("unchecked")
31 public class FairGenericObjectPool extends GenericObjectPool {
32
33     //--- constructors -----------------------------------------------
34
// (all copied from superclass; only last adds one additional line of
35
// initialization and call to superclass)
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 JavaDoc());
180     }
181     
182     //-- ObjectPool methods ------------------------------------------
183

184     /**
185      *
186      * @see org.apache.commons.pool.ObjectPool#borrowObject()
187      */

188     public Object JavaDoc borrowObject() throws Exception JavaDoc {
189         assertOpen();
190         long starttime = System.currentTimeMillis();
191         
192         
193         
194         try {
195             synchronized(this) {
196                 // use borrowerQueue
197
_borrowerQueue.add(Thread.currentThread());
198                 
199                 for(;;) {
200                     ObjectTimestampPair pair = null;
201     
202                     // Only allow current thread to receive pool object if
203
// thread is top of queue
204
boolean eligible = _borrowerQueue.get(0)==Thread.currentThread();
205                     if(eligible) {
206                         // if there are any sleeping, just grab one of those
207
try {
208                             pair = (ObjectTimestampPair)(_pool.removeFirst());
209                         } catch(NoSuchElementException JavaDoc e) {
210                             ; /* ignored */
211                         }
212                     }
213     
214                     // otherwise
215
if(null == pair) {
216                         // check if we can create one
217
// (note we know that the num sleeping is 0, else we wouldn't be here)
218
if(eligible && (_maxActive < 0 || _numActive < _maxActive)) {
219                             // allow new object to be created
220
} else {
221                             // the pool is exhausted
222
// or current thread is ineligible due to fairness
223
switch(_whenExhaustedAction) {
224                                 case WHEN_EXHAUSTED_GROW:
225                                     // allow new object to be created
226
break;
227                                 case WHEN_EXHAUSTED_FAIL:
228                                     throw new NoSuchElementException JavaDoc("Pool exhausted");
229                                 case WHEN_EXHAUSTED_BLOCK:
230                                     try {
231                                         if(_maxWait <= 0) {
232                                             wait();
233                                         } else {
234                                             // this code may be executed again after a notify then continue cycle
235
// so, need to calculate the amount of time to wait
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 JavaDoc e) {
244                                         // ignored
245
}
246                                     if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
247                                         throw new NoSuchElementException JavaDoc("Timeout waiting for idle object");
248                                     } else {
249                                         continue; // keep looping
250
}
251                                 default:
252                                     throw new IllegalArgumentException JavaDoc("WhenExhaustedAction property " + _whenExhaustedAction + " not recognized.");
253                             }
254                         }
255                     }
256                     _numActive++;
257     
258                     // create new object when needed
259
boolean newlyCreated = false;
260                     if(null == pair) {
261                         try {
262                             Object JavaDoc obj = _factory.makeObject();
263                             pair = new ObjectTimestampPair(obj);
264                             newlyCreated = true;
265                             return pair.value;
266                         } finally {
267                             if (!newlyCreated) {
268                                 // object cannot be created
269
_numActive--;
270                                 notifyAll();
271                             }
272                         }
273                     }
274     
275                     // activate & validate the object
276
try {
277                         _factory.activateObject(pair.value);
278                         if(_testOnBorrow && !_factory.validateObject(pair.value)) {
279                             throw new Exception JavaDoc("ValidateObject failed");
280                         }
281                         return pair.value;
282                     }
283                     catch (Throwable JavaDoc e) {
284                         // object cannot be activated or is invalid
285
_numActive--;
286                         notifyAll();
287                         try {
288                             _factory.destroyObject(pair.value);
289                         }
290                         catch (Throwable JavaDoc e2) {
291                             // cannot destroy broken object
292
}
293                         if(newlyCreated) {
294                             throw new NoSuchElementException JavaDoc("Could not create a validated object, cause: " + e.getMessage());
295                         }
296                         else {
297                             continue; // keep looping
298
}
299                     }
300                 }
301             }
302         } finally {
303             // remove thread from queue on any method exit
304
_borrowerQueue.remove(Thread.currentThread());
305         }
306     }
307
308     /** Waiting borrowers (threads in #borrowObject ) */
309     protected List JavaDoc _borrowerQueue;
310 }
311
Popular Tags