/Users/lyon/j4p/src/classUtils/pack/util/pool2/BasePassivationManager.java
|
1 package classUtils.pack.util.pool2;
2
3 import java.io.PrintStream;
4 import java.io.Serializable;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.Set;
8
9 import classUtils.pack.util.Terminable;
10
11 /**
12 * A Passivation thread is associated to one or more {@link ObjectPool ObjectPool}s
13 * and triggers the activation/passivation state of a Pooled object.
14 * <p>
15 * This class is abstract. Each subclass may define alternative passivation strategies.
16 *
17 * @author Cristiano Sadun
18 *
19 */
20 public abstract class BasePassivationManager
21 extends Thread
22 implements Terminable {
23
24 private volatile boolean shutdown = false;
25 private Iterator currentPool;
26 protected PrintStream logStream;
27
28 /**
29 * The set of pools monitored by this thread (contained org.sadun.util.pool2.ObjectPool).
30 */
31 protected Set monitoredPools = new HashSet();
32
33 /**
34 * The sleep time
35 */
36 protected int sleepTime;
37
38 /**
39 * Controls which pools are checked on a service cycle
40 */
41 protected boolean rotatePools=false;
42 protected int rotationRate=1;
43
44
45 /**
46 * Build a passivation thread monitoring the given pool, with the given thread name
47 * and having the given sleep time.
48 *
49 * @param pool the pool to monitor. Additional pools can be monitored by the same
50 * passivation thread by using {@link #addPool(classUtils.pack.util.pool2.ObjectPool)
51 * addPool()}
52 * @param name the thread name
53 */
54 protected BasePassivationManager(
55 ObjectPool pool,
56 String name,
57 int sleepTime) {
58 super(name);
59 this.sleepTime = sleepTime;
60 addPool(pool);
61 }
62
63 protected BasePassivationManager(String name, int sleepTime) {
64 super(name);
65 this.sleepTime = sleepTime;
66 }
67
68 protected BasePassivationManager(String name) {
69 this(name, 3600);
70 }
71
72 /**
73 * Add an {@link ObjectPool ObjectPool} to monitor.
74 * @param pool the pool to add
75 */
76 public synchronized void addPool(ObjectPool pool) {
77 monitoredPools.add(pool);
78 Object [] objs = pool.createObjectsArray();
79
80 if (objs.length>0)
81 if ( !(canPassivate(((PooledObject)objs[0])._getOriginal().getClass()))) {
82 if (logStream != null) {
83 logStream.println("Warning: class \""+objs.getClass().getComponentType()+"\" is not passivable.");
84 }
85 }
86
87 // Create the initial state map
88 for(int i=0;i<objs.length;i++) {
89 PooledObject obj = (PooledObject)objs[i];
90 createState(pool, obj);
91 }
92 if (logStream!=null)
93 logStream.println("Pool \""+pool.getName()+"\" managed by "+getName());
94 }
95
96 /**
97 * Method canPassivate.
98 * @param class
99 * @return boolean
100 */
101 public boolean canPassivate(Class cls) {
102 return Serializable.class.isAssignableFrom(cls);
103 }
104
105
106 /**
107 * Used by a subclass to define an state information for a certain object belonging to
108 * a certain pool when a pool is added to the monitored set
109 * @param obj the object
110 * @param pool the pool the object belongs to
111 */
112 protected abstract void createState(ObjectPool pool, PooledObject obj);
113
114 /**
115 * Used by a subclass to remove the state information for a certain object belonging to
116 * a certain pool when a pool is removed from the monitored set
117 * @param obj the object
118 * @param pool the pool the object belongs to
119 */
120 protected abstract void removeState(ObjectPool pool, PooledObject obj);
121
122
123 /**
124 * Remove an {@link ObjectPool ObjectPool} from monitoring.
125 * @param pool the pool to remove
126 */
127 public void removePool(ObjectPool pool) {
128 monitoredPools.remove(pool);
129 }
130
131 /**
132 * Count the monitored pools
133 * @param pool the pool to add
134 */
135 public int countPools() {
136 return monitoredPools.size();
137 }
138
139 /**
140 * The passivation thread main loop.
141 * <p>
142 * The thread awakes any {@link #sleepTime sleepTime} milliseconds
143 * and runs a service cycle, by verifying the passivability of all
144 * the objects in all or some of the monitored pools (see {@link #rotatePools
145 * rotatePools}).
146 * <p>
147 * The method {@link #isToPassivate(classUtils.pack.util.pool2.ObjectPool, classUtils.pack.util.pool2.PooledObject, java.lang.Object) isToPassivate()}
148 * is invoked on every object. If the method returns <b>true</b> the corresponding object
149 * is passivated.
150 */
151 public final void run() {
152 if (logStream!=null)
153 logStream.println(getName()+" started");
154 while (!shutdown) {
155 doPassivationCheck();
156 try {
157 sleep(sleepTime);
158 } catch (InterruptedException e) {
159 // do nothing
160 }
161 }
162 if (logStream!=null)
163 logStream.println(getName()+" terminated");
164 }
165
166 /**
167 * Method doPassivationCheck. If pools are rotated, only a subset are actually
168 * checked on any active cycle. Else, all pools are checked.
169 */
170 private void doPassivationCheck() {
171 if (rotatePools) {
172 for(int i=0;i<rotationRate;i++) {
173 if (currentPool==null) currentPool=monitoredPools.iterator();
174 else if (! currentPool.hasNext()) currentPool=monitoredPools.iterator();
175
176 ObjectPool pool = (ObjectPool)currentPool.next();
177 doPassivationCheck(pool);
178 }
179 } else {
180 for(currentPool=monitoredPools.iterator(); currentPool.hasNext();) {
181 ObjectPool pool = (ObjectPool)currentPool.next();
182 doPassivationCheck(pool);
183 }
184 }
185
186 }
187
188 /**
189 * Method doPassivationCheck. Checks an entire pool.
190 * @param pool
191 */
192 private void doPassivationCheck(ObjectPool pool) {
193 if (logStream!=null)
194 logStream.println(getName()+" checking \""+pool.getName()+"\"");
195 synchronized(pool) {
196 Object preparationResult = prepareForPassivationCheck(pool);
197 Object [] objs = pool.createObjectsArray();
198 for(int i=0;i<objs.length;i++) {
199 BasePooledObject obj = (BasePooledObject)objs[i];
200 if (! obj._isPassivableNow()) continue;
201 if (isToPassivate(pool, obj, preparationResult)) {
202 obj._passivate();
203 }
204 }
205 }
206 }
207
208 /**
209 * This method is invoked just before a pool is checked for
210 * passivation, and therefore before any
211 * {@link #isToPassivate(classUtils.pack.util.pool2.ObjectPool, classUtils.pack.util.pool2.PooledObject, java.lang.Object) isToPassivate()}
212 * is invoked.
213 * <p>
214 * A subclass may execute some preparation before the pool's
215 * object are actually scanned, and return an object as result.
216 * Such object is the passed to each subsequent {@link #isToPassivate(classUtils.pack.util.pool2.ObjectPool, classUtils.pack.util.pool2.PooledObject, java.lang.Object) isToPassivate()} invocation.
217 * <p>
218 * @param pool
219 */
220 protected abstract Object prepareForPassivationCheck(ObjectPool pool);
221
222
223
224 /**
225 * This method is invoked to check whether an object is to passivate
226 * or not.
227 */
228 protected abstract boolean isToPassivate(ObjectPool pool, PooledObject obj, Object preparationResult);
229
230 /**
231 * This method is invoked by the pool when a pooled object
232 * is aquired.
233 * @param obj the PooledObject which is being acquired
234 */
235 void invoked(ObjectPool pool, PooledObject obj) {
236 handleInvoked(pool, obj);
237 }
238
239 /**
240 * This method is invoked by the pool when a pooled object
241 * is aquired.
242 * @param obj the PooledObject which is being acquired
243 */
244 void acquired(ObjectPool pool, PooledObject obj) {
245 handleAcquired(pool, obj);
246 }
247
248 /**
249 * This method is invoked by the pool when a pooled object
250 * is released.
251 * @param obj the PooledObject which is being released
252 */
253 void released(ObjectPool pool, PooledObject obj) {
254 handleReleased(pool, obj);
255 }
256
257
258 /**
259 * This method is is used by the subclass to determine
260 * what to do when a pooled object is actually invoked.
261 * <p>
262 * The passivation thread may collect this information
263 * to implements its passivation policy.
264 *
265 * @param obj the PooledObject which is being invoked
266 */
267 protected abstract void handleInvoked(ObjectPool pool, PooledObject obj);
268
269 /**
270 * This method is used by the subclass to determine
271 * what to do when a pooled object is aquired.
272 * <p>
273 * The passivation thread may collect this information
274 * to implements its passivation policy.
275 *
276 * @param obj the PooledObject which is being acquired
277 */
278 protected abstract void handleAcquired(ObjectPool pool, PooledObject obj);
279
280 /**
281 * This method is invoked by the pool when a pooled object
282 * is released.
283 * <p>
284 * The passivation thread may collect this information
285 * to implements its passivation policy.
286 *
287 * @param obj the PooledObject which is being released
288 */
289 protected abstract void handleReleased(ObjectPool pool, PooledObject obj);
290
291 /**
292 * @see classUtils.pack.util.Terminable#isShuttingDown()
293 */
294 public boolean isShuttingDown() {
295 return shutdown;
296 }
297
298 /**
299 * @see classUtils.pack.util.Terminable#shutdown()
300 */
301 public void shutdown() {
302 if (logStream!=null)
303 logStream.println("shutting down "+getName());
304 shutdown = true;
305 interrupt();
306 }
307
308 /**
309 * Returns the sleepTime.
310 * @return int
311 */
312 public int getSleepTime() {
313 return sleepTime;
314 }
315
316 /**
317 * Sets the sleepTime.
318 * @param sleepTime The sleepTime to set
319 */
320 public void setSleepTime(int sleepTime) {
321 this.sleepTime = sleepTime;
322 }
323
324 /**
325 * Returns the rotatePools.
326 * @return boolean
327 */
328 public boolean isRotatePools() {
329 return rotatePools;
330 }
331
332 /**
333 * Sets the rotatePools.
334 * @param rotatePools The rotatePools to set
335 */
336 public void setRotatePools(boolean rotatePools) {
337 this.rotatePools = rotatePools;
338 }
339
340 /**
341 * Returns the rotationRate.
342 * @return int
343 */
344 public int getRotationRate() {
345 return rotationRate;
346 }
347
348 /**
349 * Sets the rotationRate.
350 * @param rotationRate The rotationRate to set
351 */
352 public void setRotationRate(int rotationRate) {
353 this.rotationRate = rotationRate;
354 }
355
356 /**
357 * Method setLogStream.
358 * @param logStream
359 */
360 public void setLogStream(PrintStream logStream) {
361 this.logStream=logStream;
362 }
363
364 }
365