KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > store > StoreJanitorImpl


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.cocoon.components.store;
17
18 import org.apache.avalon.framework.activity.Startable;
19 import org.apache.avalon.framework.configuration.Configurable;
20 import org.apache.avalon.framework.configuration.Configuration;
21 import org.apache.avalon.framework.configuration.ConfigurationException;
22 import org.apache.avalon.framework.logger.AbstractLogEnabled;
23 import org.apache.avalon.framework.parameters.Parameters;
24 import org.apache.avalon.framework.thread.ThreadSafe;
25
26 import java.util.ArrayList JavaDoc;
27 import java.util.Iterator JavaDoc;
28
29 /**
30  * This class is a implentation of a StoreJanitor. Store classes
31  * can register to the StoreJanitor. When memory is too low,
32  * the StoreJanitor frees the registered caches until memory is normal.
33  *
34  * @deprecated Use the Avalon Excalibur Store instead.
35  *
36  * @author <a HREF="mailto:cs@ffzj0ia9.bank.dresdner.net">Christian Schmitt</a>
37  * @author <a HREF="mailto:g-froehlich@gmx.de">Gerhard Froehlich</a>
38  * @author <a HREF="mailto:proyal@managingpartners.com">Peter Royal</a>
39  * @version CVS $Id: StoreJanitorImpl.java 30932 2004-07-29 17:35:38Z vgritsenko $
40  */

41 public class StoreJanitorImpl extends AbstractLogEnabled
42     implements StoreJanitor,
43                Configurable,
44                ThreadSafe,
45                Runnable JavaDoc,
46                Startable {
47
48     private int freememory = -1;
49     private int heapsize = -1;
50     private int cleanupthreadinterval = -1;
51     private int priority = -1;
52     private Runtime JavaDoc jvm;
53     private ArrayList JavaDoc storelist;
54     private int index = -1;
55     private static boolean doRun = false;
56     private double fraction;
57
58     /**
59      * Initialize the StoreJanitorImpl.
60      * A few options can be used :
61      * <UL>
62      * <LI>freememory = how many bytes shall be always free in the jvm</LI>
63      * <LI>heapsize = max. size of jvm memory consumption</LI>
64      * <LI>cleanupthreadinterval = how often (sec) shall run the cleanup thread</LI>
65      * <LI>threadpriority = priority of the thread (1-10). (Default: 10)</LI>
66      * </UL>
67      *
68      * @param conf the Configuration of the application
69      * @exception ConfigurationException
70      */

71     public void configure(Configuration conf) throws ConfigurationException {
72         if (this.getLogger().isDebugEnabled()) {
73             this.getLogger().debug("Configure StoreJanitorImpl");
74         }
75         this.setJVM(Runtime.getRuntime());
76
77         Parameters params = Parameters.fromConfiguration(conf);
78         this.setFreememory(params.getParameterAsInteger("freememory",1000000));
79         this.setHeapsize(params.getParameterAsInteger("heapsize",60000000));
80         this.setCleanupthreadinterval(params.getParameterAsInteger("cleanupthreadinterval",10));
81         this.setPriority(params.getParameterAsInteger( "threadpriority",
82                                         Thread.currentThread().getPriority()));
83         int percent = params.getParameterAsInteger("percent_to_free", 10);
84
85         if ((this.getFreememory() < 1)) {
86             throw new ConfigurationException("StoreJanitorImpl freememory parameter has to be greater then 1");
87         }
88         if ((this.getHeapsize() < 1)) {
89             throw new ConfigurationException("StoreJanitorImpl heapsize parameter has to be greater then 1");
90         }
91         if ((this.getCleanupthreadinterval() < 1)) {
92             throw new ConfigurationException("StoreJanitorImpl cleanupthreadinterval parameter has to be greater then 1");
93         }
94         if ((this.getPriority() < 1)) {
95             throw new ConfigurationException("StoreJanitorImpl threadpriority has to be greater then 1");
96         }
97         if ((percent > 100 && percent < 1)) {
98             throw new ConfigurationException("StoreJanitorImpl percent_to_free, has to be between 1 and 100");
99         }
100
101         this.fraction = percent / 100.0;
102         this.setStoreList(new ArrayList JavaDoc());
103     }
104
105     public void start() {
106         doRun = true;
107         Thread JavaDoc checker = new Thread JavaDoc(this);
108         if (this.getLogger().isDebugEnabled()) {
109             this.getLogger().debug("Intializing checker thread");
110         }
111         checker.setPriority(this.getPriority());
112         checker.setDaemon(true);
113         checker.setName("checker");
114         checker.start();
115     }
116
117     public void stop() {
118         doRun = false;
119     }
120
121     /**
122      * The "checker" thread checks if memory is running low in the jvm.
123      */

124     public void run() {
125         while (doRun) {
126             // amount of memory used is greater then heapsize
127
if (this.memoryLow()) {
128                 if (this.getLogger().isDebugEnabled()) {
129                     this.getLogger().debug("Invoking garbage collection, total memory = "
130                             + this.getJVM().totalMemory() + ", free memory = "
131                             + this.getJVM().freeMemory());
132                 }
133
134                 //this.freePhysicalMemory();
135

136                 if (this.getLogger().isDebugEnabled()) {
137                     this.getLogger().debug("Garbage collection complete, total memory = "
138                         + this.getJVM().totalMemory() + ", free memory = "
139                         + this.getJVM().freeMemory());
140                 }
141
142                 synchronized (this) {
143                     if (this.memoryLow() && this.getStoreList().size() > 0) {
144                         this.freeMemory();
145                         this.setIndex(this.getIndex() + 1);
146                     }
147                }
148             }
149             try {
150                 Thread.sleep(this.cleanupthreadinterval * 1000);
151             } catch (InterruptedException JavaDoc ignore) {}
152         }
153     }
154
155     /**
156      * Method to check if memory is running low in the JVM.
157      *
158      * @return true if memory is low
159      */

160     private boolean memoryLow() {
161         if (this.getLogger().isDebugEnabled()) {
162             this.getLogger().debug("JVM total Memory: " + this.getJVM().totalMemory());
163             this.getLogger().debug("JVM free Memory: " + this.getJVM().freeMemory());
164         }
165
166         if((this.getJVM().totalMemory() >= this.getHeapsize())
167             && (this.getJVM().freeMemory() < this.getFreememory())) {
168             if (this.getLogger().isDebugEnabled()) {
169                 this.getLogger().debug("Memory is low = true");
170             }
171             return true;
172         } else {
173             if (this.getLogger().isDebugEnabled()) {
174                 this.getLogger().debug("Memory is low = false");
175             }
176             return false;
177         }
178     }
179
180     /**
181      * This method register the stores
182      *
183      * @param store the store to be registered
184      */

185     public void register(Store store) {
186         this.getStoreList().add(store);
187         if (this.getLogger().isDebugEnabled()) {
188             this.getLogger().debug("Registering store instance");
189             this.getLogger().debug("Size of StoreJanitor now:"
190                                    + this.getStoreList().size());
191         }
192     }
193
194     /**
195      * This method unregister the stores
196      *
197      * @param store the store to be unregistered
198      */

199     public void unregister(Store store) {
200         this.getStoreList().remove(store);
201         if (this.getLogger().isDebugEnabled()) {
202             this.getLogger().debug("Unregister store instance");
203             this.getLogger().debug("Size of StoreJanitor now:"
204                                    + this.getStoreList().size());
205         }
206     }
207
208     /**
209      * This method return a java.util.Iterator of every registered stores
210      *
211      * <i>The iterators returned is fail-fast: if list is structurally
212      * modified at any time after the iterator is created, in any way, the
213      * iterator will throw a ConcurrentModificationException. Thus, in the
214      * face of concurrent modification, the iterator fails quickly and
215      * cleanly, rather than risking arbitrary, non-deterministic behavior at
216      * an undetermined time in the future.</i>
217      *
218      * @return a java.util.Iterator
219      */

220     public Iterator JavaDoc iterator() {
221         return this.getStoreList().iterator();
222      }
223
224     /**
225      * Round Robin alghorithm for freeing the registerd caches.
226      */

227     private void freeMemory() {
228         Store store;
229
230         try {
231             //Determine elements in Store:
232
if (this.getLogger().isDebugEnabled()) {
233                 this.getLogger().debug("StoreList size=" + this.getStoreList().size());
234                 this.getLogger().debug("Actual Index position: " + this.getIndex());
235             }
236             if (this.getIndex() < this.getStoreList().size()) {
237                 if(this.getIndex() == -1) {
238                     this.setIndex(0);
239                     store = (Store)this.getStoreList().get(this.getIndex());
240
241                     if (this.getLogger().isDebugEnabled()) {
242                         this.getLogger().debug("Freeing Store: " + this.getIndex());
243                     }
244
245                     //delete proportionate elements out of the cache as
246
//configured.
247
int limit = this.calcToFree(store);
248                     for (int i=0; i < limit; i++) {
249                         store.free();
250                     }
251                 } else {
252                     store = (Store)this.getStoreList().get(this.getIndex());
253
254                     if (this.getLogger().isDebugEnabled()) {
255                         this.getLogger().debug("Freeing Store: " + this.getIndex());
256                     }
257
258                     //delete proportionate elements out of the cache as
259
//configured.
260
int limit = this.calcToFree(store);
261                     for (int i=0; i < limit; i++) {
262                         store.free();
263                     }
264                 }
265             } else {
266                 if (this.getLogger().isDebugEnabled()) {
267                     this.getLogger().debug("Starting from the beginning");
268                 }
269
270                 this.resetIndex();
271                 this.setIndex(0);
272                 store = (Store)this.getStoreList().get(this.getIndex());
273
274                 //delete proportionate elements out of the cache as
275
//configured.
276
int limit = this.calcToFree(store);
277                 for (int i=0; i < limit; i++) {
278                     store.free();
279                 }
280             }
281         } catch(Exception JavaDoc e) {
282             this.getLogger().error("Error in freeMemory()",e);
283         }
284     }
285
286     /**
287      * This method calculates the number of Elements to be freememory
288      * out of the Cache.
289      *
290      * @param store the Store which was selected as victim
291      * @return number of elements to be removed!
292      */

293     private int calcToFree(Store store) {
294         int cnt = store.size();
295         if (cnt < 0) {
296             if (getLogger().isDebugEnabled()) {
297                 getLogger().debug("Unknown size of the store: " + store);
298             }
299             return 0;
300         }
301         return (int)(cnt * fraction);
302     }
303
304     /**
305      * This method forces the garbage collector
306     private void freePhysicalMemory() {
307         this.getJVM().runFinalization();
308         this.getJVM().gc();
309     }
310      */

311
312     private int getFreememory() {
313         return freememory;
314     }
315
316     private void setFreememory(int _freememory) {
317         this.freememory = _freememory;
318     }
319
320     private int getHeapsize() {
321         return this.heapsize;
322     }
323
324     private void setHeapsize(int _heapsize) {
325         this.heapsize = _heapsize;
326     }
327
328     private int getCleanupthreadinterval() {
329         return this.cleanupthreadinterval;
330     }
331
332     private void setCleanupthreadinterval(int _cleanupthreadinterval) {
333         this.cleanupthreadinterval = _cleanupthreadinterval;
334     }
335
336     private int getPriority() {
337         return this.priority;
338     }
339
340     private void setPriority(int _priority) {
341         this.priority = _priority;
342     }
343
344     private Runtime JavaDoc getJVM() {
345         return this.jvm;
346     }
347
348     private void setJVM(Runtime JavaDoc _runtime) {
349         this.jvm = _runtime;
350     }
351
352     private ArrayList JavaDoc getStoreList() {
353         return this.storelist;
354     }
355
356     private void setStoreList(ArrayList JavaDoc _storelist) {
357         this.storelist = _storelist;
358     }
359
360     private void setIndex(int _index) {
361         if (this.getLogger().isDebugEnabled()) {
362             this.getLogger().debug("Setting index=" + _index);
363         }
364         this.index = _index;
365     }
366
367     private int getIndex() {
368         return this.index;
369     }
370
371     private void resetIndex() {
372         if (this.getLogger().isDebugEnabled()) {
373             this.getLogger().debug("Reseting index");
374         }
375         this.index = -1;
376     }
377 }
378
Popular Tags