/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