1 23 24 package org.apache.slide.util; 25 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.Map ; 30 import java.util.Set ; 31 32 import org.apache.slide.util.logger.Logger; 33 34 import org.apache.commons.collections.LRUMap; 35 36 54 public class TxLRUObjectCache { 55 56 protected Map globalCache = null; 57 58 protected Map txChangeCaches; 59 protected Map txDeleteCaches; 60 61 protected int hits = 0; 62 protected int misses = 0; 63 64 protected String name; 65 protected Logger logger; 66 protected String logChannel; 67 protected final boolean loggingEnabled; 68 69 protected boolean noGlobalCachingInsideTx; 70 71 82 public TxLRUObjectCache(int globalCacheSize, String name, Logger logger, boolean noGlobalCachingInsideTx) { 83 if (globalCacheSize != -1) { 84 globalCache = new LRUMap(globalCacheSize); 85 } 86 txChangeCaches = new HashMap(); 87 txDeleteCaches = new HashMap(); 88 89 this.name = name; 90 this.logger = logger; 91 this.noGlobalCachingInsideTx = noGlobalCachingInsideTx; 92 93 logChannel = "TxLRUObjectCache"; 94 if (name != null) { 95 logChannel += "." + name; 96 } 97 98 loggingEnabled = logger.isEnabled(logChannel, Logger.DEBUG); 100 } 101 102 public synchronized void clear() { 103 if (globalCache != null) globalCache.clear(); 104 txChangeCaches.clear(); 105 txDeleteCaches.clear(); 106 } 107 108 public synchronized Object get(Object txId, Object key) { 109 if (txId != null) { 110 Set deleteCache = (Set ) txDeleteCaches.get(txId); 111 if (deleteCache.contains(key)) { 112 hit(txId, key); 113 return null; 115 } 116 117 Map changeCache = (Map ) txChangeCaches.get(txId); 118 Object changed = changeCache.get(key); 119 if (changed != null) { 120 hit(txId, key); 121 return changed; 123 } 124 } 125 126 if (globalCache == null) return null; 127 128 if (noGlobalCachingInsideTx && txId != null) return null; 130 131 Object global = globalCache.get(key); 133 if (global != null) { 134 hit(txId, key); 135 } else { 136 miss(txId, key); 137 } 138 return global; 139 } 140 141 public synchronized void put(Object txId, Object key, Object value) { 142 if (txId != null) { 143 Set deleteCache = (Set ) txDeleteCaches.get(txId); 145 deleteCache.remove(key); 146 147 Map changeCache = (Map ) txChangeCaches.get(txId); 148 changeCache.put(key, value); 149 150 if (loggingEnabled) { 151 logger.log(txId + " added '" + key + "'", logChannel, Logger.DEBUG); 152 } 153 } else { 154 if (globalCache != null) { 155 globalCache.put(key, value); 156 if (loggingEnabled) { 157 logger.log("Added '" + key + "'", logChannel, Logger.DEBUG); 158 } 159 } 160 } 161 } 162 163 public synchronized void remove(Object txId, Object key) { 164 if (txId != null) { 165 Map changeCache = (Map ) txChangeCaches.get(txId); 167 changeCache.remove(key); 168 169 Set deleteCache = (Set ) txDeleteCaches.get(txId); 170 deleteCache.add(key); 171 172 if (loggingEnabled) { 174 logger.log(txId + " removed '" + key + "'", logChannel, Logger.DEBUG); 175 } 176 } else { 177 if (globalCache != null) { 178 globalCache.remove(key); 179 if (loggingEnabled) { 180 logger.log("Removed '" + key + "'", logChannel, Logger.DEBUG); 181 } 182 } 183 } 184 } 185 186 202 public synchronized void remove(Object txId, Object key, String delimiter) { 203 if (txId != null) { 204 Map changeCache = (Map ) txChangeCaches.get(txId); 206 changeCache.remove(key); 207 prune(changeCache, key, delimiter); 208 209 Set deleteCache = (Set ) txDeleteCaches.get(txId); 210 deleteCache.add(key); 211 deprune(deleteCache, key, delimiter); 212 213 if (loggingEnabled) { 215 logger.log(txId + " removed '" + key + "'", logChannel, Logger.DEBUG); 216 } 217 } else { 218 if (globalCache != null) { 219 globalCache.remove(key); 220 prune(globalCache, key, delimiter); 221 if (loggingEnabled) { 222 logger.log("Removed '" + key + "'", logChannel, Logger.DEBUG); 223 } 224 } 225 } 226 } 227 228 public synchronized void start(Object txId) { 229 if (txId != null) { 230 txChangeCaches.put(txId, new HashMap()); 231 txDeleteCaches.put(txId, new HashSet ()); 232 } 233 } 234 235 public synchronized void rollback(Object txId) { 236 if (txId != null) { 237 238 if (loggingEnabled) { 239 Map changeCache = (Map ) txChangeCaches.get(txId); 240 Set deleteCache = (Set ) txDeleteCaches.get(txId); 241 logger.log( 242 txId 243 + " rolled back " 244 + changeCache.size() 245 + " changes and " 246 + deleteCache.size() 247 + " scheduled deletes", 248 logChannel, 249 Logger.DEBUG); 250 } 251 252 forget(txId); 254 } 255 } 256 257 public synchronized void commit(Object txId) { 258 if (txId != null) { 259 260 if (globalCache != null) { 261 263 Map changeCache = (Map ) txChangeCaches.get(txId); 264 for (Iterator it = changeCache.entrySet().iterator(); it.hasNext();) { 265 Map.Entry entry = (Map.Entry ) it.next(); 266 globalCache.put(entry.getKey(), entry.getValue()); 267 } 268 269 Set deleteCache = (Set ) txDeleteCaches.get(txId); 270 for (Iterator it = deleteCache.iterator(); it.hasNext();) { 271 Object key = it.next(); 272 globalCache.remove(key); 273 } 274 275 if (loggingEnabled) { 276 logger.log( 277 txId 278 + " committed " 279 + changeCache.size() 280 + " changes and " 281 + deleteCache.size() 282 + " scheduled deletes", 283 logChannel, 284 Logger.DEBUG); 285 } 286 } 287 forget(txId); 289 } 290 } 291 292 public synchronized void forget(Object txId) { 293 if (txId != null) { 294 txChangeCaches.remove(txId); 295 txDeleteCaches.remove(txId); 296 } 297 } 298 299 protected void hit(Object txId, Object key) { 300 hits++; 301 log(txId, key, true); 302 } 303 304 protected void miss(Object txId, Object key) { 305 misses++; 306 log(txId, key, false); 307 } 308 309 protected void log(Object txId, Object key, boolean hit) { 310 if (loggingEnabled) { 311 StringBuffer log = new StringBuffer (); 312 313 if (txId != null) { 314 Map changeCache = (Map ) txChangeCaches.get(txId); 315 Set deleteCache = (Set ) txDeleteCaches.get(txId); 316 log.append(txId + " (" + changeCache.size() + ", " + deleteCache.size() + ") "); 317 } 318 319 log.append( 320 (hit ? "Cache Hit: '" : "Cache Miss: '") 321 + key 322 + "' " 323 + hits 324 + " / " 325 + misses 326 + " / " 327 + (globalCache != null ? globalCache.size() : -1)); 328 logger.log(log.toString(), logChannel, Logger.DEBUG); 329 } 330 } 331 332 protected void prune(Map map, Object key, String delimiter) { 333 for (Iterator it = map.entrySet().iterator(); it.hasNext();) { 334 Map.Entry entry = (Map.Entry )it.next(); 335 if (entry.getKey().toString().startsWith(key + delimiter)) { 336 it.remove(); 337 } 338 } 339 } 340 341 protected void deprune(Set set, Object key, String delimiter) { 342 if (globalCache != null) { 343 for (Iterator it = globalCache.entrySet().iterator(); it.hasNext();) { 344 Map.Entry entry = (Map.Entry ) it.next(); 345 if (entry.getKey().toString().startsWith(key + delimiter)) { 346 set.add(entry.getKey()); 347 } 348 } 349 } 350 } 351 } 352 | Popular Tags |