1 19 package org.netbeans.modules.turbo; 20 21 import java.util.*; 22 23 38 final class Memory { 39 40 41 private final int minimumSize; 42 43 44 private final int maximumSize; 45 46 47 private final Map minimalMap; 48 49 50 private final Map liveEntitiesMap = new WeakHashMap(3571); 51 52 53 public static final Object NULL = new Object (); 54 55 56 public static final ThreadLocal prepared = new ThreadLocal (); 57 58 private final Statistics statistics; 59 60 private static final Random random = new Random(0); 61 62 68 public Memory(Statistics statistics, int minSize, int maxSize) { 69 if (maxSize != -1) { 70 if (maxSize < minSize || maxSize <1) { 71 throw new IllegalArgumentException (); 72 } 73 } 74 minimumSize = minSize; 75 maximumSize = maxSize; 76 minimalMap = new LRU(minimumSize); 77 this.statistics = statistics; 78 } 79 80 86 public synchronized void put(Object key, String name, Object value) { 87 88 90 Map attributes; 91 if (liveEntitiesMap.containsKey(key)) { 92 attributes = (Map) liveEntitiesMap.get(key); 93 } else { 94 attributes = (Map) minimalMap.get(key); 95 if (attributes == null) { 96 attributes = new HashMap(5); 97 } 98 } 99 100 102 if (value != null) { 103 attributes.put(name, normalizeValue(value)); 104 } else { 105 attributes.remove(name); 106 } 107 putLive(key, attributes); 108 minimalMap.put(key, attributes); 109 Entry entry = (Entry) prepared.get(); 110 if (entry != null) { 111 if (key.equals(entry.key) && name.equals(entry.name)) { 112 if (value != null) { 113 entry.value = normalizeValue(value); 114 } else { 115 prepared.set(null); 116 } 117 } 118 } 119 } 120 121 private void putLive(Object key, Map attributes) { 122 123 if (maximumSize != -1 && liveEntitiesMap.size() >= maximumSize) { 126 Set keySet = liveEntitiesMap.keySet(); 127 List l = new ArrayList(liveEntitiesMap.keySet()); 128 129 if(l.size() == maximumSize) { 131 int limit = Math.min(7, maximumSize/10); 132 for (int i = 0; i<limit; i++) { 133 int index = random.nextInt(maximumSize); 134 Object removed = l.get(index); 135 if (keySet.remove(removed)) { 136 statistics.keyRemoved(removed); 137 } 138 } 139 } 140 141 } 142 143 liveEntitiesMap.put(key, attributes); 144 statistics.keyAdded(key); 145 } 146 147 private static Object normalizeValue(Object value) { 148 if (value == NULL) return null; 149 return value; 150 } 151 152 156 public synchronized Object get(Object key, String name) { 157 158 Map attributes = (Map) liveEntitiesMap.get(key); 159 if (attributes != null) { 160 return attributes.get(name); 161 } 162 163 attributes = (Map) minimalMap.get(key); 165 if (attributes != null) { 166 putLive(key, attributes); 167 return attributes.get(name); 168 } 169 170 Entry entry = (Entry) prepared.get(); 172 if (entry != null) { 173 if (key.equals(entry.key) && name.equals(entry.name)) { 174 prepared.set(null); return entry.value; 176 } 177 } 178 179 return null; 180 } 181 182 187 public synchronized boolean existsEntry(Object key, String name) { 188 Map attributes = (Map) liveEntitiesMap.get(key); 189 if (attributes == null) { 190 attributes = (Map) minimalMap.get(key); 191 } 192 193 boolean isPrepared = attributes != null && attributes.keySet().contains(name); 195 if (isPrepared) { 196 Entry entry = (Entry) prepared.get(); 197 if (entry == null) { 198 entry = new Entry(); 199 } 200 entry.key = key; 201 entry.name = name; 202 entry.value = attributes.get(name); 203 prepared.set(entry); 204 } else { 205 statistics.computeRemoved(liveEntitiesMap.keySet()); 206 prepared.set(null); 207 } 208 return isPrepared; 209 } 210 211 public synchronized Object getMonitoredKey(Object key) { 212 Set keySet = liveEntitiesMap.keySet(); 213 if (keySet.contains(key)) { 214 Iterator it = keySet.iterator(); 215 while (it.hasNext()) { 216 Object next = it.next(); 217 if (key.equals(next)) { 218 return next; 219 } 220 } 221 } 222 return null; 223 } 224 225 226 private class Entry { 227 private Object key; 228 private String name; 229 private Object value; 230 } 231 232 233 private final static class LRU extends LinkedHashMap { 234 235 private final int maxSize; 236 237 public LRU(int maxSize) { 238 super(maxSize *2, 0.5f, true); 239 this.maxSize = maxSize; 240 } 241 242 protected boolean removeEldestEntry(Map.Entry eldest) { 243 return size() > maxSize; 244 } 245 } 246 247 } 248 | Popular Tags |