1 8 package org.ozoneDB.core.storage; 9 10 import java.lang.ref.ReferenceQueue ; 11 import java.lang.ref.WeakReference ; 12 import java.util.Properties ; 13 import java.util.logging.Level ; 14 import java.util.logging.Logger ; 15 import org.ozoneDB.core.ConfigurationException; 16 import org.ozoneDB.core.storage.DelayCache.TimedEntry; 17 18 23 public class GcListeningDelayCache extends DelayCache { 24 25 private static Logger log = Logger.getLogger(GcListeningDelayCache.class.getName()); 26 27 public static final PropertyInfo HIGHTHRESHOLD = new PropertyInfo( 28 ".highThreshold", 29 "int", 30 "10000000", 31 "when free memory falls below this threshold this cache will start throwing out elements", 32 new String [] {"10000", "50000000"} 33 ); 34 35 public static final PropertyInfo LOWTHRESHOLD = new PropertyInfo( 36 ".lowThreshold", 37 "int", 38 "-1000000", 39 "when free memory falls below this threshold this cache will throw out all elements (may be < 0)", 40 new String [] {"1000", "-500000"} 41 ); 42 43 46 private WeakReference gcIndicator; 47 48 private ReferenceQueue gcQueue = new ReferenceQueue (); 49 private Thread gcIndicatorThread = new GcIndicatorThread(); 50 51 private long lowThreshold; 52 private long highThreshold; 53 54 public GcListeningDelayCache(Properties properties, String prefix) { 55 super(properties, prefix); 56 gcIndicatorThread.start(); 57 try { 58 lowThreshold = Integer.parseInt(properties.getProperty(prefix + LOWTHRESHOLD.getKey(), LOWTHRESHOLD.getDefaultValue())); 59 log.config(getPrefix() + " using a low threshold of " + lowThreshold); 60 highThreshold = Integer.parseInt(properties.getProperty(prefix + HIGHTHRESHOLD.getKey(), HIGHTHRESHOLD.getDefaultValue())); 61 log.config(getPrefix() + " using a high threshold of " + highThreshold); 62 } catch (NumberFormatException e) { 63 throw new ConfigurationException(e); 64 } 65 } 66 67 72 private final void resetGcIndicator() { 73 gcIndicator = new WeakReference (new Object (), gcQueue); 74 } 75 76 private void ourGC() { 77 synchronized(getSynchronizer()) { 78 if (size() > 0) { 79 long freeMemory = Runtime.getRuntime().freeMemory(); 80 if (freeMemory < getHighThreshold()) { 81 96 float clearRatio = (float) (freeMemory - getHighThreshold()) / (float) (getLowThreshold() - getHighThreshold()); 97 if (clearRatio > 0) { 98 if (clearRatio > 1) { 99 clearRatio = 1; 100 } 101 if (log.isLoggable(Level.FINE)) log.fine("removing " + clearRatio + " from cache"); 102 int numToClear = (int) (size() * clearRatio); 103 if (numToClear < 1) { 104 numToClear = 1; 105 } 106 for (;numToClear > 0; numToClear--) { 107 TimedEntry last = (TimedEntry) getEntries().last(); 108 if (getTrimHandler() != null) { 109 getTrimHandler().trimming(last.key, last.value); 110 } 111 getEntries().remove(last); 112 getKeysToEntries().remove(last.key); 113 } 114 } 115 } 116 } 117 } 118 } 119 120 124 public void setHighThreshold(long highThreshold) { 125 synchronized(getSynchronizer()) { 126 if (highThreshold <= getLowThreshold()) { 127 String msg = "could not set highThreshold to " + highThreshold + "; must be > lowThreshold (" + getLowThreshold() + ")"; 128 log.severe(msg); 129 throw new IllegalArgumentException (msg); 130 } 131 this.highThreshold = highThreshold; 132 } 133 } 134 135 139 public void setLowThreshold(long lowThreshold) { 140 synchronized(getSynchronizer()) { 141 if (lowThreshold < 0 || lowThreshold >= getHighThreshold()) { 142 String msg = "could not set lowThreshold to " + lowThreshold + "; must be >= 0 and <= highThreshold (" + getHighThreshold() + ")"; 143 log.severe(msg); 144 throw new IllegalArgumentException (msg); 145 } 146 this.lowThreshold = lowThreshold; 147 } 148 } 149 150 public long getHighThreshold() { 151 synchronized(getSynchronizer()) { 152 return highThreshold; 153 } 154 } 155 156 public synchronized long getLowThreshold() { 157 synchronized(getSynchronizer()) { 158 return lowThreshold; 159 } 160 } 161 162 167 private class GcIndicatorThread extends Thread { 168 169 GcIndicatorThread() { 170 super(Thread.currentThread().getThreadGroup(), "gc indicator"); 171 setDaemon(true); 172 setPriority(Thread.MAX_PRIORITY - 1); 175 } 176 177 public void run() { 178 for (;;) { 179 try { 180 resetGcIndicator(); 181 182 gcQueue.remove(); 184 if (log.isLoggable(Level.FINE)) { 185 Runtime runtime = Runtime.getRuntime(); 186 log.fine("gc has kicked in (free mem: " + runtime.freeMemory() + ", total mem: " + runtime.totalMemory()); 187 } 188 ourGC(); 189 } catch (InterruptedException ignore) { 190 } 191 } 192 } 193 194 } 195 196 198 static class Item { 199 byte[] filling = new byte[100]; 200 private Object key; 201 202 Item(Object key) { 203 this.key = key; 204 } 205 206 public String toString() { 207 return key.toString(); 208 } 209 210 } 211 212 public static void main(String [] args) { 213 Properties properties = new Properties (); 214 String prefix = "dbg"; 215 properties.setProperty(prefix + LOWTHRESHOLD.getKey(), "-32000000"); 216 properties.setProperty(prefix + HIGHTHRESHOLD.getKey(), "1000000"); 217 properties.setProperty(prefix + DELAY.getKey(), "2000"); 218 GcListeningDelayCache cache = new GcListeningDelayCache(properties, prefix); 219 220 for (int i = 0; ; i++ ) { 221 Object key = new Integer (i); 222 Item item = new Item(key); 223 cache.put(key, item); 225 if (i > 10) { 226 } 228 229 if (cache.size() % 100 == 0) { 230 System.out.println("references in map: " + cache.size() + ", free: " + Runtime.getRuntime().freeMemory()); 231 } 232 } 233 } 235 236 } 237 | Popular Tags |