1 22 package org.jboss.ejb.plugins; 23 24 import java.util.ArrayList ; 25 import java.util.Timer ; 26 import java.util.TimerTask ; 27 28 import org.jboss.deployment.DeploymentException; 29 import org.jboss.ejb.EnterpriseContext; 30 import org.jboss.logging.Logger; 31 import org.jboss.metadata.MetaData; 32 import org.jboss.metadata.XmlLoadable; 33 import org.jboss.monitor.Monitorable; 34 import org.jboss.monitor.client.BeanCacheSnapshot; 35 import org.jboss.util.LRUCachePolicy; 36 import org.w3c.dom.Element ; 37 38 46 public class LRUEnterpriseContextCachePolicy extends LRUCachePolicy 47 implements XmlLoadable, Monitorable 48 { 49 51 protected static Logger log = Logger.getLogger(LRUEnterpriseContextCachePolicy.class); 53 protected static Timer tasksTimer = new Timer (true); 54 static 55 { 56 log.debug("Cache policy timer started, tasksTimer="+tasksTimer); 57 } 58 59 60 private AbstractInstanceCache m_cache; 61 62 63 private long m_resizerPeriod; 64 65 66 private long m_overagerPeriod; 67 68 69 private long m_maxBeanAge; 70 71 75 private long m_minPeriod; 76 77 81 private long m_maxPeriod; 82 83 87 private double m_factor; 88 89 90 private TimerTask m_overager; 91 92 93 private TimerTask m_resizer; 94 95 96 private StringBuffer m_buffer = new StringBuffer (); 97 98 99 101 103 107 public LRUEnterpriseContextCachePolicy(AbstractInstanceCache eic) 108 { 109 if (eic == null) 110 throw new IllegalArgumentException 111 ("Instance cache argument cannot be null"); 112 113 m_cache = eic; 114 } 115 116 118 120 public void sample(Object s) 121 { 122 if( m_cache == null ) 123 return; 124 125 BeanCacheSnapshot snapshot = (BeanCacheSnapshot)s; 126 LRUList list = getList(); 127 synchronized (m_cache.getCacheLock()) 128 { 129 snapshot.m_cacheMinCapacity = list.m_minCapacity; 130 snapshot.m_cacheMaxCapacity = list.m_maxCapacity; 131 snapshot.m_cacheCapacity = list.m_capacity; 132 snapshot.m_cacheSize = list.m_count; 133 } 134 } 135 136 138 public void start() 139 { 140 if (m_resizerPeriod > 0) 141 { 142 m_resizer = new ResizerTask(m_resizerPeriod); 143 long delay = (long) (Math.random() * m_resizerPeriod); 144 tasksTimer.schedule(m_resizer, delay, m_resizerPeriod); 145 } 146 147 if (m_overagerPeriod > 0) 148 { 149 m_overager = new OveragerTask(m_overagerPeriod); 150 long delay = (long) (Math.random() * m_overagerPeriod); 151 tasksTimer.schedule(m_overager, delay, m_overagerPeriod); 152 } 153 } 154 155 public void stop() 156 { 157 if (m_resizer != null) {m_resizer.cancel();} 158 if (m_overager != null) {m_overager.cancel();} 159 super.stop(); 160 } 161 162 public void destroy() 163 { 164 m_overager = null; 165 m_resizer = null; 166 m_cache = null; 167 super.destroy(); 168 } 169 170 180 public void importXml(Element element) throws DeploymentException 181 { 182 String min = MetaData.getElementContent(MetaData.getOptionalChild(element, "min-capacity")); 183 String max = MetaData.getElementContent(MetaData.getOptionalChild(element, "max-capacity")); 184 String op = MetaData.getElementContent(MetaData.getOptionalChild(element, "overager-period")); 185 String rp = MetaData.getElementContent(MetaData.getOptionalChild(element, "resizer-period")); 186 String ma = MetaData.getElementContent(MetaData.getOptionalChild(element, "max-bean-age")); 187 String map = MetaData.getElementContent(MetaData.getOptionalChild(element, "max-cache-miss-period")); 188 String mip = MetaData.getElementContent(MetaData.getOptionalChild(element, "min-cache-miss-period")); 189 String fa = MetaData.getElementContent(MetaData.getOptionalChild(element, "cache-load-factor")); 190 try 191 { 192 if (min != null) 193 { 194 int s = Integer.parseInt(min); 195 if (s <= 0) 196 { 197 throw new DeploymentException("Min cache capacity can't be <= 0"); 198 } 199 m_minCapacity = s; 200 } 201 if (max != null) 202 { 203 int s = Integer.parseInt(max); 204 if (s <= 0) 205 { 206 throw new DeploymentException("Max cache capacity can't be <= 0"); 207 } 208 m_maxCapacity = s; 209 } 210 if (op != null) 211 { 212 int p = Integer.parseInt(op); 213 if (p <= 0) {throw new DeploymentException("Overager period can't be <= 0");} 214 m_overagerPeriod = p * 1000; 215 } 216 if (rp != null) 217 { 218 int p = Integer.parseInt(rp); 219 if (p <= 0) {throw new DeploymentException("Resizer period can't be <= 0");} 220 m_resizerPeriod = p * 1000; 221 } 222 if (ma != null) 223 { 224 int a = Integer.parseInt(ma); 225 if (a <= 0) {throw new DeploymentException("Max bean age can't be <= 0");} 226 m_maxBeanAge = a * 1000; 227 } 228 if (map != null) 229 { 230 int p = Integer.parseInt(map); 231 if (p <= 0) {throw new DeploymentException("Max cache miss period can't be <= 0");} 232 m_maxPeriod = p * 1000; 233 } 234 if (mip != null) 235 { 236 int p = Integer.parseInt(mip); 237 if (p <= 0) {throw new DeploymentException("Min cache miss period can't be <= 0");} 238 m_minPeriod = p * 1000; 239 } 240 if (fa != null) 241 { 242 double f = Double.parseDouble(fa); 243 if (f <= 0.0) {throw new DeploymentException("Cache load factor can't be <= 0");} 244 m_factor = f; 245 } 246 } 247 catch (NumberFormatException x) 248 { 249 throw new DeploymentException("Can't parse policy configuration", x); 250 } 251 } 252 253 255 262 public void flush() 263 { 264 int i = size(); 265 LRUCacheEntry entry = null; 266 while (i-- > 0 && (entry = m_list.m_tail) != null) 267 { 268 ageOut(entry); 269 } 270 } 271 272 274 276 protected LRUList createList() 277 { 278 return new ContextLRUList(); 279 } 280 281 282 protected void ageOut(LRUCacheEntry entry) 283 { 284 if( m_cache == null ) 285 return; 286 287 if (entry == null) 288 { 289 throw new IllegalArgumentException 290 ("Cannot remove a null cache entry"); 291 } 292 293 if( log.isTraceEnabled() ) 294 { 295 m_buffer.setLength(0); 296 m_buffer.append("Aging out from cache bean "); 297 m_buffer.append(m_cache.getContainer().getBeanMetaData().getEjbName()); 298 m_buffer.append("with id = "); 299 m_buffer.append(entry.m_key); 300 m_buffer.append("; cache size = "); 301 m_buffer.append(getList().m_count); 302 log.trace(m_buffer.toString()); 303 } 304 305 m_cache.release((EnterpriseContext)entry.m_object); 307 } 308 protected void cacheMiss() 309 { 310 LRUList list = getList(); 311 ++list.m_cacheMiss; 312 } 313 314 316 private LRUList getList() 317 { 318 return m_list; 319 } 320 321 323 330 protected class ResizerTask extends TimerTask 331 { 332 private String m_message; 333 private StringBuffer m_buffer; 334 private long resizerPeriod; 335 336 protected ResizerTask(long resizerPeriod) 337 { 338 this.resizerPeriod = resizerPeriod; 339 m_message = "Resized cache for bean " + 340 m_cache.getContainer().getBeanMetaData().getEjbName() + 341 ": old capacity = "; 342 m_buffer = new StringBuffer (); 343 } 344 345 public void run() 346 { 347 if( m_cache == null ) 349 { 350 cancel(); 351 return; 352 } 353 354 LRUList list = getList(); 355 356 synchronized (m_cache.getCacheLock()) 358 { 359 int period = list.m_cacheMiss == 0 ? Integer.MAX_VALUE : (int)(resizerPeriod / list.m_cacheMiss); 360 int cap = list.m_capacity; 361 if (period <= m_minPeriod && cap < list.m_maxCapacity) 362 { 363 double factor = 1.0 + ((double)m_minPeriod / period) * (1.0 - m_factor); 366 int newCap = (int)(cap * factor); 367 list.m_capacity = newCap < list.m_maxCapacity ? newCap : list.m_maxCapacity; 368 log(cap, list.m_capacity); 369 } 370 else if (period >= m_maxPeriod && 371 cap > list.m_minCapacity && 372 list.m_count < (cap * m_factor)) 373 { 374 int newCap = (int)(list.m_count / m_factor); 376 list.m_capacity = newCap > list.m_minCapacity ? newCap : list.m_minCapacity; 377 log(cap, list.m_capacity); 378 } 379 list.m_cacheMiss = 0; 380 } 381 } 382 383 private void log(int oldCapacity, int newCapacity) 384 { 385 if( log.isTraceEnabled() ) 386 { 387 m_buffer.setLength(0); 388 m_buffer.append(m_message); 389 m_buffer.append(oldCapacity); 390 m_buffer.append(", new capacity = "); 391 m_buffer.append(newCapacity); 392 log.trace(m_buffer.toString()); 393 } 394 } 395 } 396 397 400 protected class OveragerTask extends TimerTask 401 { 402 private String m_message; 403 private StringBuffer m_buffer; 404 405 protected OveragerTask(long period) 406 { 407 m_message = getTaskLogMessage() + " " + 408 m_cache.getContainer().getBeanMetaData().getEjbName() + 409 " with id = "; 410 m_buffer = new StringBuffer (); 411 } 412 413 public void run() 414 { 415 if( m_cache == null ) 416 { 417 cancel(); 418 return; 419 } 420 421 LRUList list = getList(); 422 long now = System.currentTimeMillis(); 423 ArrayList passivateEntries = null; 424 synchronized (m_cache.getCacheLock()) 425 { 426 for (LRUCacheEntry entry = list.m_tail; entry != null; entry = entry.m_prev) 427 { 428 if (now - entry.m_time >= getMaxAge()) 429 { 430 if (passivateEntries == null) passivateEntries = new ArrayList (); 432 passivateEntries.add(entry); 433 } 434 else 435 { 436 break; 437 } 438 } 439 } 440 if (passivateEntries != null) 444 { 445 for (int i = 0; i < passivateEntries.size(); i++) 446 { 447 LRUCacheEntry entry = (LRUCacheEntry) passivateEntries.get(i); 448 try 449 { 450 m_cache.tryToPassivate((EnterpriseContext) entry.m_object); 451 } 452 catch (Throwable t) 453 { 454 log.debug("Ignored error while trying to passivate ctx", t); 455 } 456 } 457 } 458 } 459 460 private void log(Object key, int count) 461 { 462 if( log.isTraceEnabled() ) 463 { 464 m_buffer.setLength(0); 465 m_buffer.append(m_message); 466 m_buffer.append(key); 467 m_buffer.append(" - Cache size = "); 468 m_buffer.append(count); 469 log.trace(m_buffer.toString()); 470 } 471 } 472 473 protected String getTaskLogMessage() 474 { 475 return "Scheduling for passivation overaged bean"; 476 } 477 478 protected String getJMSTaskType() 479 { 480 return "OVERAGER"; 481 } 482 483 protected long getMaxAge() 484 { 485 return m_maxBeanAge; 486 } 487 } 488 489 492 protected class ContextLRUList extends LRUList 493 { 494 boolean trace = log.isTraceEnabled(); 495 protected void entryPromotion(LRUCacheEntry entry) 496 { 497 if (trace) 498 log.trace("entryPromotion, entry="+entry); 499 500 if (m_count == m_capacity && m_capacity >= m_maxCapacity) 502 { 503 ++m_capacity; 504 log.warn("Cache has reached maximum capacity for container " + 505 m_cache.getContainer().getJmxName() + 506 " - probably because all instances are in use. " + 507 "Temporarily increasing the size to " + m_capacity); 508 } 509 } 510 protected void entryAdded(LRUCacheEntry entry) 511 { 512 if (trace) 513 log.trace("entryAdded, entry="+entry); 514 } 515 protected void entryRemoved(LRUCacheEntry entry) 516 { 517 if (trace) 518 log.trace("entryRemoved, entry="+entry); 519 } 520 protected void capacityChanged(int oldCapacity) 521 { 522 if (trace) 523 log.trace("capacityChanged, oldCapacity="+oldCapacity); 524 } 525 } 526 527 } 528 | Popular Tags |