1 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 ; 27 import java.util.Iterator ; 28 29 41 public class StoreJanitorImpl extends AbstractLogEnabled 42 implements StoreJanitor, 43 Configurable, 44 ThreadSafe, 45 Runnable , 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 jvm; 53 private ArrayList storelist; 54 private int index = -1; 55 private static boolean doRun = false; 56 private double fraction; 57 58 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 ()); 103 } 104 105 public void start() { 106 doRun = true; 107 Thread checker = new Thread (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 124 public void run() { 125 while (doRun) { 126 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 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 ignore) {} 152 } 153 } 154 155 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 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 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 220 public Iterator iterator() { 221 return this.getStoreList().iterator(); 222 } 223 224 227 private void freeMemory() { 228 Store store; 229 230 try { 231 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 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 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 int limit = this.calcToFree(store); 277 for (int i=0; i < limit; i++) { 278 store.free(); 279 } 280 } 281 } catch(Exception e) { 282 this.getLogger().error("Error in freeMemory()",e); 283 } 284 } 285 286 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 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 getJVM() { 345 return this.jvm; 346 } 347 348 private void setJVM(Runtime _runtime) { 349 this.jvm = _runtime; 350 } 351 352 private ArrayList getStoreList() { 353 return this.storelist; 354 } 355 356 private void setStoreList(ArrayList _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 |