/* */ package org.jboss.ejb3.cache.simple;
/* */
/* */ import java.util.Iterator;
/* */ import java.util.LinkedHashMap;
/* */ import java.util.List;
/* */ import java.util.Map.Entry;
/* */ import java.util.Set;
/* */ import javax.ejb.EJBException;
/* */ import javax.ejb.NoSuchEJBException;
/* */ import javax.management.ObjectName;
/* */ import org.jboss.aop.Advisor;
/* */ import org.jboss.ejb3.Container;
/* */ import org.jboss.ejb3.EJBContainer;
/* */ import org.jboss.ejb3.Ejb3Deployment;
/* */ import org.jboss.ejb3.annotation.CacheConfig;
/* */ import org.jboss.ejb3.annotation.PersistenceManager;
/* */ import org.jboss.ejb3.cache.StatefulCache;
/* */ import org.jboss.ejb3.cache.persistence.PersistenceManagerFactory;
/* */ import org.jboss.ejb3.cache.persistence.PersistenceManagerFactoryRegistry;
/* */ import org.jboss.ejb3.pool.Pool;
/* */ import org.jboss.ejb3.stateful.StatefulBeanContext;
/* */ import org.jboss.logging.Logger;
/* */
/* */ public class SimpleStatefulCache
/* */ implements StatefulCache
/* */ {
/* 51 */ private Logger log = Logger.getLogger(SimpleStatefulCache.class);
/* */ private Pool pool;
/* */ private CacheMap cacheMap;
/* 55 */ private int maxSize = 1000;
/* */ private StatefulSessionPersistenceManager pm;
/* 57 */ private long sessionTimeout = 300L;
/* 58 */ private long removalTimeout = 0L;
/* */ private SessionTimeoutTask timeoutTask;
/* 60 */ private RemovalTimeoutTask removalTask = null;
/* 61 */ private boolean running = true;
/* 62 */ private int createCount = 0;
/* 63 */ private int passivatedCount = 0;
/* 64 */ private int removeCount = 0;
/* */
/* */ public void initialize(Container container)
/* */ throws Exception
/* */ {
/* 245 */ Advisor advisor = (Advisor)container;
/* 246 */ this.pool = container.getPool();
/* 247 */ this.cacheMap = new CacheMap();
/* 248 */ PersistenceManager pmConfig = (PersistenceManager)advisor.resolveAnnotation(PersistenceManager.class);
/* 249 */ EJBContainer ejbContainer = (EJBContainer)container;
/* 250 */ this.pm = ejbContainer.getDeployment().getPersistenceManagerFactoryRegistry().getPersistenceManagerFactory(pmConfig.value()).createPersistenceManager();
/* */
/* 252 */ this.pm.initialize(container);
/* 253 */ CacheConfig config = (CacheConfig)advisor.resolveAnnotation(CacheConfig.class);
/* 254 */ this.maxSize = config.maxSize();
/* 255 */ this.sessionTimeout = config.idleTimeoutSeconds();
/* 256 */ this.removalTimeout = config.removalTimeoutSeconds();
/* 257 */ this.log = Logger.getLogger(getClass().getName() + "." + container.getEjbName());
/* 258 */ this.log.debug("Initializing SimpleStatefulCache with maxSize: " + this.maxSize + " timeout: " + this.sessionTimeout + " for " + container.getObjectName().getCanonicalName());
/* */
/* 260 */ this.timeoutTask = new SessionTimeoutTask("SFSB Passivation Thread - " + container.getObjectName().getCanonicalName());
/* */
/* 262 */ if (this.removalTimeout > 0L)
/* 263 */ this.removalTask = new RemovalTimeoutTask("SFSB Removal Thread - " + container.getObjectName().getCanonicalName());
/* */ }
/* */
/* */ public void start()
/* */ {
/* 272 */ this.running = true;
/* 273 */ this.timeoutTask.start();
/* */
/* 275 */ if (this.removalTask != null)
/* 276 */ this.removalTask.start();
/* */ }
/* */
/* */ public void stop()
/* */ {
/* 281 */ synchronized (this.cacheMap)
/* */ {
/* 283 */ this.running = false;
/* 284 */ this.timeoutTask.interrupt();
/* 285 */ if (this.removalTask != null)
/* 286 */ this.removalTask.interrupt();
/* 287 */ this.cacheMap.clear();
/* */ try
/* */ {
/* 290 */ this.pm.destroy();
/* */ }
/* */ catch (Exception e)
/* */ {
/* 294 */ throw new RuntimeException(e);
/* */ }
/* */ }
/* */ }
/* */
/* */ protected void passivate(StatefulBeanContext ctx)
/* */ {
/* 301 */ ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
/* */ try
/* */ {
/* 304 */ Thread.currentThread().setContextClassLoader(ctx.getContainer().getClassloader());
/* 305 */ this.pm.passivateSession(ctx);
/* 306 */ this.passivatedCount += 1;
/* */ }
/* */ finally
/* */ {
/* 310 */ Thread.currentThread().setContextClassLoader(oldCl);
/* */ }
/* */ }
/* */
/* */ public StatefulBeanContext create()
/* */ {
/* 316 */ StatefulBeanContext ctx = null;
/* */ try
/* */ {
/* 319 */ ctx = (StatefulBeanContext)this.pool.get();
/* */
/* 321 */ if (this.log.isTraceEnabled())
/* */ {
/* 323 */ this.log.trace("Caching context " + ctx.getId() + " of type " + ctx.getClass());
/* */ }
/* 325 */ synchronized (this.cacheMap)
/* */ {
/* 327 */ this.cacheMap.put(ctx.getId(), ctx);
/* */ }
/* 329 */ ctx.setInUse(true);
/* 330 */ ctx.lastUsed = System.currentTimeMillis();
/* 331 */ this.createCount += 1;
/* */ }
/* */ catch (EJBException e)
/* */ {
/* 335 */ e.printStackTrace();
/* 336 */ throw e;
/* */ }
/* */ catch (Exception e)
/* */ {
/* 340 */ e.printStackTrace();
/* 341 */ throw new EJBException(e);
/* */ }
/* 343 */ return ctx;
/* */ }
/* */
/* */ public StatefulBeanContext create(Class[] initTypes, Object[] initValues)
/* */ {
/* 348 */ StatefulBeanContext ctx = null;
/* */ try
/* */ {
/* 351 */ ctx = (StatefulBeanContext)this.pool.get(initTypes, initValues);
/* 352 */ if (this.log.isTraceEnabled())
/* */ {
/* 354 */ this.log.trace("Caching context " + ctx.getId() + " of type " + ctx.getClass());
/* */ }
/* 356 */ synchronized (this.cacheMap)
/* */ {
/* 358 */ this.cacheMap.put(ctx.getId(), ctx);
/* */ }
/* 360 */ ctx.setInUse(true);
/* 361 */ ctx.lastUsed = System.currentTimeMillis();
/* 362 */ this.createCount += 1;
/* */ }
/* */ catch (EJBException e)
/* */ {
/* 366 */ e.printStackTrace();
/* 367 */ throw e;
/* */ }
/* */ catch (Exception e)
/* */ {
/* 371 */ e.printStackTrace();
/* 372 */ throw new EJBException(e);
/* */ }
/* 374 */ return ctx;
/* */ }
/* */
/* */ public StatefulBeanContext get(Object key) throws EJBException
/* */ {
/* 379 */ return get(key, true);
/* */ }
/* */
/* */ public StatefulBeanContext get(Object key, boolean markInUse) throws EJBException
/* */ {
/* 384 */ StatefulBeanContext entry = null;
/* 385 */ synchronized (this.cacheMap)
/* */ {
/* 387 */ entry = (StatefulBeanContext)this.cacheMap.get(key);
/* */ }
/* 389 */ if (entry == null)
/* */ {
/* 391 */ entry = this.pm.activateSession(key);
/* 392 */ if (entry == null)
/* */ {
/* 394 */ throw new NoSuchEJBException("Could not find stateful bean: " + key);
/* */ }
/* 396 */ this.passivatedCount -= 1;
/* */
/* 400 */ if (this.log.isTraceEnabled())
/* */ {
/* 402 */ this.log.trace("Caching activated context " + entry.getId() + " of type " + entry.getClass());
/* */ }
/* */
/* 405 */ synchronized (this.cacheMap)
/* */ {
/* 407 */ this.cacheMap.put(key, entry);
/* */ }
/* */
/* */ }
/* */
/* 412 */ if (markInUse)
/* */ {
/* 414 */ if (entry.isRemoved())
/* */ {
/* 416 */ throw new NoSuchEJBException("Could not find stateful bean: " + key + " (bean was marked as removed");
/* */ }
/* */
/* 420 */ entry.setInUse(true);
/* 421 */ entry.lastUsed = System.currentTimeMillis();
/* */ }
/* */
/* 424 */ return entry;
/* */ }
/* */
/* */ public StatefulBeanContext peek(Object key) throws NoSuchEJBException
/* */ {
/* 429 */ return get(key, false);
/* */ }
/* */
/* */ public void release(StatefulBeanContext ctx)
/* */ {
/* 434 */ synchronized (ctx)
/* */ {
/* 436 */ ctx.setInUse(false);
/* 437 */ ctx.lastUsed = System.currentTimeMillis();
/* 438 */ if (ctx.markedForPassivation)
/* */ {
/* 440 */ passivate(ctx);
/* */ }
/* */ }
/* */ }
/* */
/* */ public void remove(Object key)
/* */ {
/* 447 */ if (this.log.isTraceEnabled())
/* */ {
/* 449 */ this.log.trace("Removing context " + key);
/* */ }
/* 451 */ StatefulBeanContext ctx = null;
/* 452 */ synchronized (this.cacheMap)
/* */ {
/* 454 */ ctx = (StatefulBeanContext)this.cacheMap.get(key);
/* */ }
/* 456 */ if (ctx != null)
/* */ {
/* 458 */ if (!ctx.isRemoved()) {
/* 459 */ this.pool.remove(ctx);
/* */ }
/* 461 */ this.removeCount += 1;
/* */
/* 463 */ if (ctx.getCanRemoveFromCache())
/* */ {
/* 465 */ synchronized (this.cacheMap)
/* */ {
/* 467 */ this.cacheMap.remove(key);
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ public int getCacheSize()
/* */ {
/* 477 */ return this.cacheMap.size();
/* */ }
/* */
/* */ public int getTotalSize()
/* */ {
/* 482 */ return getCacheSize() + getPassivatedCount();
/* */ }
/* */
/* */ public int getCreateCount()
/* */ {
/* 487 */ return this.createCount;
/* */ }
/* */
/* */ public int getPassivatedCount()
/* */ {
/* 492 */ return this.passivatedCount;
/* */ }
/* */
/* */ public int getRemoveCount()
/* */ {
/* 497 */ return this.removeCount;
/* */ }
/* */
/* */ public int getAvailableCount()
/* */ {
/* 502 */ return -1;
/* */ }
/* */
/* */ public int getMaxSize()
/* */ {
/* 507 */ return this.maxSize;
/* */ }
/* */
/* */ public int getCurrentSize()
/* */ {
/* 512 */ return this.cacheMap.size();
/* */ }
/* */
/* */ private class SessionTimeoutTask extends Thread
/* */ {
/* */ public SessionTimeoutTask(String name)
/* */ {
/* 173 */ super();
/* */ }
/* */
/* */ public void run()
/* */ {
/* 178 */ while (SimpleStatefulCache.this.running)
/* */ {
/* */ try
/* */ {
/* 182 */ Thread.sleep(SimpleStatefulCache.this.sessionTimeout * 1000L);
/* */ }
/* */ catch (InterruptedException e)
/* */ {
/* 186 */ SimpleStatefulCache.access$102(SimpleStatefulCache.this, false);
/* 187 */ return;
/* */ }
/* */ try
/* */ {
/* 191 */ synchronized (SimpleStatefulCache.this.cacheMap)
/* */ {
/* 193 */ if (!SimpleStatefulCache.this.running) return;
/* */
/* 195 */ boolean trace = SimpleStatefulCache.this.log.isTraceEnabled();
/* 196 */ Iterator it = SimpleStatefulCache.this.cacheMap.entrySet().iterator();
/* 197 */ long now = System.currentTimeMillis();
/* 198 */ while (it.hasNext())
/* */ {
/* 200 */ Map.Entry entry = (Map.Entry)it.next();
/* 201 */ StatefulBeanContext centry = (StatefulBeanContext)entry.getValue();
/* 202 */ if (now - centry.lastUsed >= SimpleStatefulCache.this.sessionTimeout * 1000L)
/* */ {
/* 204 */ synchronized (centry)
/* */ {
/* 206 */ if (centry.getCanPassivate())
/* */ {
/* 208 */ if (!centry.getCanRemoveFromCache())
/* */ {
/* 210 */ SimpleStatefulCache.this.passivate(centry);
/* */ }
/* 212 */ else if (trace)
/* */ {
/* 214 */ SimpleStatefulCache.this.log.trace("Removing " + entry.getKey() + " from cache");
/* */ }
/* */ }
/* */ else
/* */ {
/* 219 */ centry.markedForPassivation = true;
/* 220 */ assert (centry.isInUse()) : (centry + " is not in use, and thus will never be passivated");
/* */ }
/* */
/* 224 */ it.remove();
/* */ }
/* */ }
/* 227 */ else if (trace)
/* */ {
/* 229 */ SimpleStatefulCache.this.log.trace("Not passivating; id=" + centry.getId() + " only inactive " + Math.max(0L, now - centry.lastUsed) + " ms");
/* */ }
/* */ }
/* */ }
/* */
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 237 */ SimpleStatefulCache.this.log.error("problem passivation thread", ex);
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ private class RemovalTimeoutTask extends Thread
/* */ {
/* */ public RemovalTimeoutTask(String name)
/* */ {
/* 110 */ super();
/* */ }
/* */
/* */ public void run()
/* */ {
/* 115 */ while (SimpleStatefulCache.this.running)
/* */ {
/* */ try
/* */ {
/* 119 */ Thread.sleep(SimpleStatefulCache.this.removalTimeout * 1000L);
/* */ }
/* */ catch (InterruptedException e)
/* */ {
/* 123 */ SimpleStatefulCache.access$102(SimpleStatefulCache.this, false);
/* 124 */ return;
/* */ }
/* */ try
/* */ {
/* 128 */ long now = System.currentTimeMillis();
/* */
/* 130 */ synchronized (SimpleStatefulCache.this.cacheMap)
/* */ {
/* 132 */ if (!SimpleStatefulCache.this.running) return;
/* */
/* 134 */ Iterator it = SimpleStatefulCache.this.cacheMap.entrySet().iterator();
/* 135 */ while (it.hasNext())
/* */ {
/* 137 */ Map.Entry entry = (Map.Entry)it.next();
/* 138 */ StatefulBeanContext centry = (StatefulBeanContext)entry.getValue();
/* 139 */ if (now - centry.lastUsed >= SimpleStatefulCache.this.removalTimeout * 1000L)
/* */ {
/* 141 */ synchronized (centry)
/* */ {
/* 143 */ it.remove();
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* 149 */ List beans = SimpleStatefulCache.this.pm.getPassivatedBeans();
/* 150 */ Iterator it = beans.iterator();
/* 151 */ while (it.hasNext())
/* */ {
/* 153 */ StatefulBeanContext centry = (StatefulBeanContext)it.next();
/* 154 */ if (now - centry.lastUsed >= SimpleStatefulCache.this.removalTimeout * 1000L)
/* */ {
/* 156 */ SimpleStatefulCache.this.get(centry.getId(), false);
/* 157 */ SimpleStatefulCache.this.remove(centry.getId());
/* */ }
/* */ }
/* */ }
/* */ catch (Exception ex)
/* */ {
/* 163 */ SimpleStatefulCache.this.log.error("problem removing SFSB thread", ex);
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ private class CacheMap extends LinkedHashMap
/* */ {
/* */ private static final long serialVersionUID = 4514182777643616159L;
/* */
/* */ public CacheMap()
/* */ {
/* 72 */ super(0.75F, true);
/* */ }
/* */
/* */ public boolean removeEldestEntry(Map.Entry entry)
/* */ {
/* 77 */ boolean removeIt = size() > SimpleStatefulCache.this.maxSize;
/* 78 */ if (removeIt)
/* */ {
/* 80 */ StatefulBeanContext centry = (StatefulBeanContext)entry.getValue();
/* 81 */ synchronized (centry)
/* */ {
/* 83 */ if (centry.getCanPassivate())
/* */ {
/* 85 */ SimpleStatefulCache.this.passivate(centry);
/* */ }
/* */ else
/* */ {
/* 90 */ centry.markedForPassivation = true;
/* */
/* 92 */ if (!centry.isInUse())
/* */ {
/* 97 */ removeIt = false;
/* */ }
/* */ }
/* */ }
/* */ }
/* 102 */ return removeIt;
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.ejb3.cache.simple.SimpleStatefulCache
* JD-Core Version: 0.6.0
*/