1 package org.jboss.cache.eviction; 2 3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.jboss.cache.Fqn; 6 import org.jboss.cache.FqnComparator; 7 import org.jboss.cache.Region; 8 9 import java.util.Iterator ; 10 import java.util.SortedSet ; 11 import java.util.TreeSet ; 12 13 66 public class ExpirationAlgorithm extends BaseEvictionAlgorithm 67 { 68 69 private static final Log log = LogFactory.getLog(ExpirationAlgorithm.class); 70 71 private ExpirationConfiguration config; 72 73 private ExpirationPolicy policy; 74 75 private SortedSet <ExpirationEntry> set; 76 77 80 public ExpirationAlgorithm(ExpirationPolicy policy) 81 { 82 this.policy = policy; 83 this.set = new TreeSet <ExpirationEntry>(); 84 } 85 86 private void addEvictionEntry(EvictedEventNode node) 87 { 88 Fqn fqn = node.getFqn(); 89 addEvictionEntry(fqn); 90 } 91 92 private void addEvictionEntry(Fqn fqn) 93 { 94 Long l = getExpiration(fqn); 95 if (l == null) 96 { 97 if (config.getWarnNoExpirationKey()) 98 log.warn("No expiration key '" + config.getExpirationKeyName() + "' for Node: " + fqn); 99 else if (log.isDebugEnabled()) 100 log.debug("No expiration key for Node: " + fqn); 101 } 102 else 103 { 104 setExpiration(fqn, l); 105 } 106 } 107 108 private void setExpiration(Fqn fqn, Long l) 109 { 110 boolean found = set.remove(new ExpirationEntry(fqn)); 111 if (found && log.isTraceEnabled()) 112 log.trace("removed old expiration for " + fqn); 113 ExpirationEntry ee = new ExpirationEntry(fqn, l); 114 if (log.isTraceEnabled()) 115 log.trace("adding eviction entry: " + ee); 116 set.add(ee); 117 } 118 119 private Long getExpiration(Fqn fqn) 120 { 121 Long l = (Long ) policy.getCacheData(fqn, config.getExpirationKeyName()); 122 if (l == null) 123 return null; 124 return l; 125 } 126 127 @Override 128 protected void processQueues(Region region) throws EvictionException 129 { 130 EvictedEventNode node; 131 int count = 0; 132 while ((node = region.takeLastEventNode()) != null) 133 { 134 count++; 135 switch (node.getEventType()) 136 { 137 case ADD_NODE_EVENT: 138 case ADD_ELEMENT_EVENT: 139 addEvictionEntry(node); 140 break; 141 case REMOVE_ELEMENT_EVENT: 142 case REMOVE_NODE_EVENT: 143 case UNMARK_USE_EVENT: 144 removeEvictionEntry(node); 145 break; 146 case VISIT_NODE_EVENT: 147 break; 149 case MARK_IN_USE_EVENT: 150 markInUse(node); 151 break; 152 default: 153 throw new RuntimeException ("Illegal Eviction Event type " + node.getEventType()); 154 } 155 } 156 157 if (log.isTraceEnabled()) 158 { 159 log.trace("processed " + count + " node events in region: " + region.getFqn()); 160 } 161 } 162 163 private void markInUse(EvictedEventNode node) 164 { 165 long expiration = node.getInUseTimeout() + System.currentTimeMillis(); 166 setExpiration(node.getFqn(), expiration); 167 } 168 169 @Override 170 protected void prune() throws EvictionException 171 { 172 if (set.isEmpty()) 173 return; 174 long now = System.currentTimeMillis(); 175 int max = config.getMaxNodes(); 176 for (Iterator <ExpirationEntry> i = set.iterator(); i.hasNext();) 177 { 178 ExpirationEntry ee = i.next(); 179 if (ee.getExpiration() < now || (max != 0 && set.size() > max)) 180 { 181 i.remove(); 182 evictCacheNode(ee.getFqn()); 183 } 184 else 185 { 186 break; 187 } 188 } 189 if (max != 0 && max > set.size()) 190 log.warn("Unable to remove nodes to reduce region size below " + 191 config.getMaxNodes() + ". " + 192 "Set expiration for nodes in this region"); 193 } 194 195 private void removeEvictionEntry(EvictedEventNode node) 196 { 197 Fqn fqn = node.getFqn(); 198 if (getExpiration(fqn) == null) 199 set.remove(new ExpirationEntry(fqn)); 200 } 201 202 @Override 203 public void resetEvictionQueue(Region region) 204 { 205 for (ExpirationEntry ee : set) 206 { 207 addEvictionEntry(ee.getFqn()); 208 } 209 } 210 211 @Override 212 protected EvictionQueue setupEvictionQueue(Region region) throws EvictionException 213 { 214 this.region = region; 215 this.config = (ExpirationConfiguration) region.getEvictionPolicyConfig(); 216 return new DummyEvictionQueue(); 217 } 218 219 @Override 220 protected boolean shouldEvictNode(NodeEntry ne) 221 { 222 throw new UnsupportedOperationException (); 223 } 224 225 229 static class ExpirationEntry implements Comparable <ExpirationEntry> 230 { 231 232 private long expiration; 233 234 private Fqn fqn; 235 236 public ExpirationEntry(Fqn fqn) 237 { 238 this.fqn = fqn; 239 } 240 241 public ExpirationEntry(Fqn fqn, long expiration) 242 { 243 this.fqn = fqn; 244 this.expiration = expiration; 245 } 246 247 250 public int compareTo(ExpirationEntry ee) 251 { 252 if (fqn.equals(ee.fqn)) 253 return 0; 254 long n = expiration - ee.expiration; 255 if (n < 0) 256 return -1; 257 if (n > 0) 258 return 1; 259 return FqnComparator.INSTANCE.compare(fqn, ee.fqn); 260 } 261 262 265 public long getExpiration() 266 { 267 return expiration; 268 } 269 270 273 public Fqn getFqn() 274 { 275 return fqn; 276 } 277 278 public boolean equals(Object o) 279 { 280 if (!(o instanceof ExpirationEntry)) 281 return false; 282 ExpirationEntry ee = (ExpirationEntry) o; 283 return fqn.equals(ee.fqn); 284 } 285 286 public int hashCode() 287 { 288 return fqn.hashCode(); 289 } 290 291 public String toString() 292 { 293 long now = System.currentTimeMillis(); 294 long ttl = expiration - now; 295 String sttl; 296 if (ttl > 1000 * 60) 297 sttl = (ttl / (1000 * 60)) + "min"; 298 else if (ttl > 1000) 299 sttl = (ttl / 1000) + "s"; 300 else 301 sttl = ttl + "ms"; 302 return "EE fqn=" + fqn + " ttl=" + sttl; 303 } 304 } 305 306 class DummyEvictionQueue implements EvictionQueue 307 { 308 309 public void addNodeEntry(NodeEntry entry) 310 { 311 throw new UnsupportedOperationException (); 312 } 313 314 public void clear() 315 { 316 set.clear(); 317 } 318 319 public boolean containsNodeEntry(NodeEntry entry) 320 { 321 return false; 322 } 323 324 public NodeEntry getFirstNodeEntry() 325 { 326 return null; 327 } 328 329 public NodeEntry getNodeEntry(Fqn fqn) 330 { 331 return null; 332 } 333 334 public NodeEntry getNodeEntry(String fqn) 335 { 336 return null; 337 } 338 339 public int getNumberOfElements() 340 { 341 return set.size(); 342 } 343 344 public int getNumberOfNodes() 345 { 346 return set.size(); 347 } 348 349 public Iterator iterate() 350 { 351 return null; 352 } 353 354 public void modifyElementCount(int difference) 355 { 356 } 357 358 public void removeNodeEntry(NodeEntry entry) 359 { 360 throw new UnsupportedOperationException (); 361 } 362 363 } 364 365 } 366 | Popular Tags |