Author: vgritsenko Date: Wed Mar 9 12:40:44 2005 New Revision: 156681 URL: http://svn.apache.org/viewcvs?view=rev&rev=156681 Log: cleanups
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/store/impl/StoreJanitorImpl.java Modified: cocoon/trunk/src/java/org/apache/cocoon/components/store/impl/StoreJanitorImpl.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/store/impl/StoreJanitorImpl.java?view=diff&r1=156680&r2=156681 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/store/impl/StoreJanitorImpl.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/components/store/impl/StoreJanitorImpl.java Wed Mar 9 12:40:44 2005 @@ -1,16 +1,16 @@ -/* +/* * Copyright 2002-2004 The Apache Software Foundation * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * + * You may obtain a copy of the License at + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. - * + * * See the License for the specific language governing permissions and * limitations under the License. */ @@ -32,7 +32,21 @@ * This class is a implentation of a StoreJanitor. Store classes * can register to the StoreJanitor. When memory is too low, * the StoreJanitor frees the registered caches until memory is normal. - * + * + * <p>A few parameters can be used: + * <UL> + * <LI><B>freememory</B>: How many bytes shall be always free in the JVM (Default: 1mb)</LI> + * <LI><B>heapsize</B>: Maximum possible size of the JVM memory consumption (Default: 64mb)</LI> + * <LI><B>cleanupthreadinterval</B>: How often (sec) shall run the cleanup thread (Default: 10s)</LI> + * <LI><B>adaptivethreadinterval</B> (experimental): Enable adaptive algorithm to determine thread interval + * (Default: false) When true, <code>cleanupthreadinterval</code> defines the maximum cleanup interval. + * Cleanup interval then is determined based on the memory fill rate: the faster memory is filled in, + * and the less free memory is left, the shorter is the cleanup time.</LI> + * <LI><B>threadpriority</B>: priority of the thread (1-10). (Default: 10)</LI> + * <LI><B>percent_to_free</B>: What fraction of the store to free when memory is low (1-100). (Default: 10%)</LI> + * <LI><B>invokegc</B>: Invoke the gc on low memory first (true|false; default: false)</LI> + * </UL></p> + * * @avalon.component * @avalon.service type=StoreJanitor * @x-avalon.info name=store-janitor @@ -41,120 +55,91 @@ * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a> * @version CVS $Id: StoreJanitorImpl.java,v 1.4 2004/02/28 11:47:31 cziegeler Exp $ */ -public class StoreJanitorImpl -extends AbstractLogEnabled -implements StoreJanitor, - Parameterizable, - ThreadSafe, - Runnable, - Startable -{ - - private boolean doRun = false; +public class StoreJanitorImpl extends AbstractLogEnabled + implements StoreJanitor, Parameterizable, ThreadSafe, + Runnable, Startable { // Configuration parameters private int minFreeMemory = -1; private int maxHeapSize = -1; private int threadInterval = -1; private int minThreadInterval = 500; - private boolean adaptiveThreadInterval = false; + private boolean adaptiveThreadInterval; private int priority = -1; private double fraction; private Runtime jvm; private ArrayList storelist; private int index = -1; + /** Should the gc be called on low memory? */ - protected boolean invokeGC = false; - /** - * Amount of memory in use before sleep(). Must be initially set a resonable + protected boolean invokeGC; + + private boolean doRun; + + /** + * Amount of memory in use before sleep(). Must be initially set a resonable * value; ie. <code>memoryInUse()</code> */ protected long inUse; + private boolean firstRun = true; - /** The calculated delay for the next checker run */ - protected long interval = Long.MAX_VALUE; // Sleep time in ms - private long maxRateOfChange = 1; // Used memory change rate in bytes per second + + /** The calculated delay for the next checker run in ms */ + protected long interval = Long.MAX_VALUE; + + /** Used memory change rate in bytes per second */ + private long maxRateOfChange = 1; + /** - * Initialize the StoreJanitorImpl. - * A few options can be used : - * <UL> - * <LI><B>freememory</B>: How many bytes shall be always free in the JVM (Default: 1mb)</LI> - * <LI><B>heapsize</B>: Maximum possible size of the JVM memory consumption (Default: 64mb)</LI> - * <LI><B>cleanupthreadinterval</B>: How often (sec) shall run the cleanup thread (Default: 10s)</LI> - * <LI><B>adaptivethreadinterval</B> (experimental): Enable adaptive algorithm to determine thread interval - * (Default: false) When true, <code>cleanupthreadinterval</code> defines the maximum cleanup interval. - * Cleanup interval then is determined based on the memory fill rate: the faster memory is filled in, - * and the less free memory is left, the shorter is the cleanup time.</LI> - * <LI><B>threadpriority</B>: priority of the thread (1-10). (Default: 10)</LI> - * <LI><B>percent_to_free</B>: What fraction of the store to free when memory is low (1-100). (Default: 10%)</LI> - * <LI><B>invokegc</B>: Invoke the gc on low memory first (true|false; default: false)</LI> - * </UL> - * - * @param params the Configuration of the application - * @exception ParameterException + * Parameterize the StoreJanitorImpl. */ - public void parameterize(Parameters params) throws ParameterException - { - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Configure StoreJanitorImpl"); - } - setJVM(Runtime.getRuntime()); - - setMinFreeMemory(params.getParameterAsInteger("freememory", 1024 * 1024)); - setMaxHeapSize(params.getParameterAsInteger("heapsize", 60 * 1024 * 1024)); + public void parameterize(Parameters params) throws ParameterException { + this.jvm = Runtime.getRuntime(); + this.minFreeMemory = params.getParameterAsInteger("freememory", 1024 * 1024); + this.maxHeapSize = params.getParameterAsInteger("heapsize", 60 * 1024 * 1024); // Parameter value is in seconds, converted to millis - setThreadInterval(params.getParameterAsInteger("cleanupthreadinterval", 10) * 1000); - setAdaptiveThreadInterval(params.getParameterAsBoolean("adaptivethreadinterval", false)); - setPriority(params.getParameterAsInteger("threadpriority", - Thread.currentThread().getPriority())); + this.threadInterval = params.getParameterAsInteger("cleanupthreadinterval", 10) * 1000; + this.adaptiveThreadInterval = params.getParameterAsBoolean("adaptivethreadinterval", false); + this.priority = params.getParameterAsInteger("threadpriority", Thread.currentThread().getPriority()); int percent = params.getParameterAsInteger("percent_to_free", 10); this.invokeGC = params.getParameterAsBoolean("invokegc", this.invokeGC); - - if (getMinFreeMemory() < 1) - { + + if (getMinFreeMemory() < 1) { throw new ParameterException("StoreJanitorImpl freememory parameter has to be greater then 1"); } - if (getMaxHeapSize() < 1) - { + if (getMaxHeapSize() < 1) { throw new ParameterException("StoreJanitorImpl heapsize parameter has to be greater then 1"); } - if (getThreadInterval() < 1) - { + if (getThreadInterval() < 1) { throw new ParameterException("StoreJanitorImpl cleanupthreadinterval parameter has to be greater then 1"); } - if (getPriority() < 1 || getPriority() > 10) - { + if (getPriority() < 1 || getPriority() > 10) { throw new ParameterException("StoreJanitorImpl threadpriority has to be between 1 and 10"); } - if (percent > 100 && percent < 1) - { + if (percent > 100 && percent < 1) { throw new ParameterException("StoreJanitorImpl percent_to_free, has to be between 1 and 100"); } this.fraction = percent / 100.0D; - setStoreList(new ArrayList()); - - if ( getLogger().isDebugEnabled() ) - { - getLogger().debug("minimum free memory=" + this.getMinFreeMemory()); - getLogger().debug("heapsize=" + this.getMaxHeapSize()); - getLogger().debug("thread interval=" + this.getThreadInterval()); - getLogger().debug("adaptivethreadinterval=" + this.getAdaptiveThreadInterval()); - getLogger().debug("priority=" + this.getPriority()); + this.storelist = new ArrayList(); + + if (getLogger().isDebugEnabled()) { + getLogger().debug("minimum free memory=" + getMinFreeMemory()); + getLogger().debug("heapsize=" + getMaxHeapSize()); + getLogger().debug("thread interval=" + getThreadInterval()); + getLogger().debug("adaptivethreadinterval=" + getAdaptiveThreadInterval()); + getLogger().debug("priority=" + getPriority()); getLogger().debug("percent=" + percent); getLogger().debug("invoke gc=" + this.invokeGC); } } - public void start() - { - doRun = true; + public void start() throws Exception { + this.doRun = true; Thread checker = new Thread(this); - if (getLogger().isDebugEnabled()) - { + if (getLogger().isDebugEnabled()) { getLogger().debug("Intializing checker thread"); } checker.setPriority(getPriority()); @@ -163,36 +148,31 @@ checker.start(); } - public void stop() - { - doRun = false; + public void stop() { + this.doRun = false; } /** * The "checker" thread loop. */ - public void run() - { - inUse = memoryInUse(); - while (doRun) { + public void run() { + this.inUse = memoryInUse(); + while (this.doRun) { checkMemory(); // Sleep - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Sleeping for " + interval + "ms"); - } - try - { - Thread.sleep(interval); - } - catch (InterruptedException ignore) {} + if (getLogger().isDebugEnabled()) { + getLogger().debug("Sleeping for " + this.interval + "ms"); + } + try { + Thread.sleep(this.interval); + } catch (InterruptedException ignore) { + } // Ignore change in memory during the first run (startup) - if (firstRun) - { - firstRun = false; - inUse = memoryInUse(); + if (this.firstRun) { + this.firstRun = false; + this.inUse = memoryInUse(); } } } @@ -200,15 +180,12 @@ /** * The "checker" thread checks if memory is running low in the jvm. */ - protected void checkMemory() - { - if (getAdaptiveThreadInterval()) - { + protected void checkMemory() { + if (getAdaptiveThreadInterval()) { // Monitor the rate of change of heap in use. long change = memoryInUse() - inUse; long rateOfChange = longDiv(change * 1000, interval); // bps. - if (maxRateOfChange < rateOfChange) - { + if (maxRateOfChange < rateOfChange) { maxRateOfChange = (maxRateOfChange + rateOfChange) / 2; } if (getLogger().isDebugEnabled()) { @@ -219,68 +196,53 @@ } // Amount of memory used is greater than heapsize - if (memoryLow()) - { - if ( this.invokeGC ) - { - this.freePhysicalMemory(); + if (memoryLow()) { + if (this.invokeGC) { + freePhysicalMemory(); } - synchronized (this) - { + synchronized (this) { if (!this.invokeGC - || (memoryLow() && getStoreList().size() > 0)) - { - + || (memoryLow() && getStoreList().size() > 0)) { + freeMemory(); setIndex(getIndex() + 1); } } } - if (getAdaptiveThreadInterval()) - { + if (getAdaptiveThreadInterval()) { // Calculate sleep interval based on the change rate and free memory left interval = minTimeToFill(maxRateOfChange) * 1000 / 2; - if (interval > this.threadInterval) - { + if (interval > this.threadInterval) { interval = this.threadInterval; - } - else if (interval < this.minThreadInterval) - { + } else if (interval < this.minThreadInterval) { interval = this.minThreadInterval; } inUse = memoryInUse(); - } - else - { + } else { interval = this.threadInterval; } } + /** * Method to check if memory is running low in the JVM. * * @return true if memory is low */ - private boolean memoryLow() - { - if (getLogger().isDebugEnabled()) - { + private boolean memoryLow() { + if (getLogger().isDebugEnabled()) { getLogger().debug("JVM Memory total: " + getJVM().totalMemory() + ", free: " + getJVM().freeMemory()); } if ((getJVM().totalMemory() >= getMaxHeapSize()) - && (getJVM().freeMemory() < getMinFreeMemory())) - { - if (getLogger().isDebugEnabled()) - { + && (getJVM().freeMemory() < getMinFreeMemory())) { + if (getLogger().isDebugEnabled()) { getLogger().debug("Memory is low!"); } return true; - } - else - { + } else { return false; } } @@ -290,8 +252,7 @@ * * @return memory in use. */ - protected long memoryInUse() - { + protected long memoryInUse() { return jvm.totalMemory() - jvm.freeMemory(); } @@ -302,19 +263,14 @@ * @param rate memory fill rate in time per bytes * @return amount of time to fill all the memory with given fill rate */ - private long minTimeToFill(long rate) - { + private long minTimeToFill(long rate) { return longDiv(jvm.freeMemory(), rate); } - private long longDiv(long top, long bottom) - { - try - { + private long longDiv(long top, long bottom) { + try { return top / bottom; - } - catch (Exception e) - { + } catch (Exception e) { return top > 0 ? Long.MAX_VALUE : Long.MIN_VALUE; } } @@ -324,11 +280,9 @@ * * @param store the store to be registered */ - public synchronized void register(Store store) - { + public synchronized void register(Store store) { getStoreList().add(store); - if (getLogger().isDebugEnabled()) - { + if (getLogger().isDebugEnabled()) { getLogger().debug("Registered store instance " + store + ". Stores now: " + getStoreList().size()); } @@ -339,11 +293,9 @@ * * @param store the store to be unregistered */ - public synchronized void unregister(Store store) - { + public synchronized void unregister(Store store) { getStoreList().remove(store); - if (getLogger().isDebugEnabled()) - { + if (getLogger().isDebugEnabled()) { getLogger().debug("Unregistered store instance " + store + ". Stores now: " + getStoreList().size()); } @@ -361,32 +313,24 @@ * * @return a java.util.Iterator */ - public Iterator iterator() - { + public Iterator iterator() { return getStoreList().iterator(); } /** * Round Robin alghorithm for freeing the registered caches. */ - private void freeMemory() - { + private void freeMemory() { // TODO: Alternative to RR might be to free same fraction from every storage. - try - { + try { // Determine the store. - if (getIndex() < getStoreList().size()) - { - if (getIndex() == -1) - { + if (getIndex() < getStoreList().size()) { + if (getIndex() == -1) { setIndex(0); } - } - else - { + } else { // Store list changed (one or more store has been removed). - if (getLogger().isDebugEnabled()) - { + if (getLogger().isDebugEnabled()) { getLogger().debug("Restarting from the beginning"); } setIndex(0); @@ -395,28 +339,20 @@ // Delete proportionate elements out of the store as configured. Store store = (Store)getStoreList().get(getIndex()); int limit = calcToFree(store); - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Freeing " + limit + " items from store N " + getIndex()); - } - for (int i=0; i < limit; i++) - { - try - { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Freeing " + limit + " items from store #" + getIndex()); + } + + for (int i = 0; i < limit; i++) { + try { store.free(); - } - catch (OutOfMemoryError e) - { + } catch (OutOfMemoryError e) { getLogger().error("OutOfMemoryError in freeMemory()"); } } - } - catch (Exception e) - { + } catch (Exception e) { getLogger().error("Error in freeMemory()", e); - } - catch (OutOfMemoryError e) - { + } catch (OutOfMemoryError e) { getLogger().error("OutOfMemoryError in freeMemory()"); } } @@ -428,21 +364,18 @@ * @param store the Store which was selected as victim * @return number of elements to be removed! */ - private int calcToFree(Store store) - { + private int calcToFree(Store store) { int cnt = store.size(); - if (cnt < 0) - { - if ( getLogger().isDebugEnabled() ) - { + if (cnt < 0) { + if (getLogger().isDebugEnabled()) { getLogger().debug("Unknown size of the store: " + store); } return 0; } - final int res = (int)(cnt * fraction); - if ( getLogger().isDebugEnabled() ) - { - getLogger().debug("Calculating size for store " + store + " with size " + cnt + " : " + res); + + final int res = (int) (cnt * fraction); + if (getLogger().isDebugEnabled()) { + getLogger().debug("Calculating size for store " + store + " with size " + cnt + ": " + res); } return res; } @@ -450,11 +383,9 @@ /** * This method forces the garbage collector */ - private void freePhysicalMemory() - { - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Invoking garbage collection. Memory total: " + private void freePhysicalMemory() { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Invoking GC. Memory total: " + getJVM().totalMemory() + ", free: " + getJVM().freeMemory()); } @@ -462,96 +393,50 @@ getJVM().runFinalization(); getJVM().gc(); - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Garbage collection complete. Memory total: " + if (getLogger().isDebugEnabled()) { + getLogger().debug("GC complete. Memory total: " + getJVM().totalMemory() + ", free: " + getJVM().freeMemory()); } } - - private int getMinFreeMemory() - { - return this.minFreeMemory; - } - private void setMinFreeMemory(int _freememory) - { - this.minFreeMemory = _freememory; + private int getMinFreeMemory() { + return this.minFreeMemory; } - private int getMaxHeapSize() - { + private int getMaxHeapSize() { return this.maxHeapSize; } - private void setMaxHeapSize(int _heapsize) - { - this.maxHeapSize = _heapsize; - } - - private int getPriority() - { + private int getPriority() { return this.priority; } - private void setPriority(int _priority) - { - this.priority = _priority; - } - - private int getThreadInterval() - { + private int getThreadInterval() { return this.threadInterval; } - private void setThreadInterval(int _threadInterval) - { - this.threadInterval = _threadInterval; - } - - private boolean getAdaptiveThreadInterval() - { + private boolean getAdaptiveThreadInterval() { return this.adaptiveThreadInterval; } - private void setAdaptiveThreadInterval(boolean _adaptiveThreadInterval) - { - this.adaptiveThreadInterval = _adaptiveThreadInterval; - } - - private Runtime getJVM() - { + private Runtime getJVM() { return this.jvm; } - private void setJVM(Runtime _jvm) - { - this.jvm = _jvm; - } - - private ArrayList getStoreList() - { + private ArrayList getStoreList() { return this.storelist; } - private void setStoreList(ArrayList _storelist) - { - this.storelist = _storelist; - } - - private void setIndex(int _index) - { - if (getLogger().isDebugEnabled()) - { + private void setIndex(int _index) { + if (getLogger().isDebugEnabled()) { getLogger().debug("Setting index=" + _index); } this.index = _index; } - private int getIndex() - { + private int getIndex() { return this.index; } }