1 22 package org.jboss.ejb3.cache.simple; 23 24 import java.util.Iterator ; 25 import java.util.LinkedHashMap ; 26 import java.util.Map ; 27 import javax.ejb.EJBException ; 28 import javax.ejb.NoSuchEJBException ; 29 import org.jboss.annotation.ejb.cache.simple.CacheConfig; 30 import org.jboss.annotation.ejb.cache.simple.PersistenceManager; 31 import org.jboss.aop.Advisor; 32 import org.jboss.ejb3.Container; 33 import org.jboss.ejb3.EJBContainer; 34 import org.jboss.ejb3.Pool; 35 import org.jboss.ejb3.cache.StatefulCache; 36 import org.jboss.ejb3.stateful.StatefulBeanContext; 37 import org.jboss.util.id.GUID; 38 import org.jboss.logging.Logger; 39 40 46 public class SimpleStatefulCache implements StatefulCache 47 { 48 private static final Logger log = Logger.getLogger(SimpleStatefulCache.class); 49 50 private Pool pool; 51 private CacheMap cacheMap; 52 private int maxSize = 1000; 53 private StatefulSessionPersistenceManager pm; 54 private long sessionTimeout = 300; private SessionTimeoutTask timeoutTask; 56 private boolean running = true; 57 58 private class CacheMap extends LinkedHashMap 59 { 60 public CacheMap() 61 { 62 super(maxSize, 0.75F, true); 63 } 64 65 public boolean removeEldestEntry(Map.Entry entry) 66 { 67 boolean removeIt = size() > maxSize; 68 if (removeIt) 69 { 70 StatefulBeanContext centry = (StatefulBeanContext) entry.getValue(); 71 synchronized (centry) 72 { 73 if (centry.inUse) 74 { 75 centry.markedForPassivation = true; 76 } 77 else 78 { 79 passivate(centry); 80 } 81 } 83 } 84 return removeIt; 85 } 86 } 87 88 private class SessionTimeoutTask extends Thread 89 { 90 public SessionTimeoutTask(String name) 91 { 92 super(name); 93 } 94 95 public void run() 96 { 97 while (running) 98 { 99 try 100 { 101 Thread.sleep(sessionTimeout * 1000); 102 } 103 catch (InterruptedException e) 104 { 105 running = false; 106 return; 107 } 108 try 109 { 110 synchronized (cacheMap) 111 { 112 if (!running) return; 113 Iterator it = cacheMap.entrySet().iterator(); 114 long now = System.currentTimeMillis(); 115 while (it.hasNext()) 116 { 117 Map.Entry entry = (Map.Entry ) it.next(); 118 StatefulBeanContext centry = (StatefulBeanContext) entry.getValue(); 119 if (now - centry.lastUsed >= sessionTimeout * 1000) 120 { 121 synchronized (centry) 122 { 123 if (centry.inUse) 124 { 125 centry.markedForPassivation = true; 126 } 127 else 128 { 129 passivate(centry); 130 } 131 it.remove(); 133 } 134 } 135 } 136 } 137 } 138 catch (Exception ex) 139 { 140 log.error("problem passivation thread", ex); 141 } 142 } 143 } 144 } 145 146 public void initialize(Container container) throws Exception 147 { 148 Advisor advisor = (Advisor) container; 149 this.pool = container.getPool(); 150 cacheMap = new CacheMap(); 151 PersistenceManager pmConfig = (PersistenceManager) advisor.resolveAnnotation(PersistenceManager.class); 152 this.pm = (StatefulSessionPersistenceManager) pmConfig.value().newInstance(); 153 pm.initialize(container); 154 CacheConfig config = (CacheConfig) advisor.resolveAnnotation(CacheConfig.class); 155 maxSize = config.maxSize(); 156 sessionTimeout = config.idleTimeoutSeconds(); 157 log.debug("Initializing SimpleStatefulCache with maxSize: " +maxSize + " timeout: " +sessionTimeout + 158 " for " +container.getObjectName().getCanonicalName() ); 159 timeoutTask = new SessionTimeoutTask("SFSB Passivation Thread - " + container.getObjectName().getCanonicalName()); 160 } 161 162 public SimpleStatefulCache() 163 { 164 } 165 166 public void start() 167 { 168 running = true; 169 timeoutTask.start(); 170 } 171 172 public void stop() 173 { 174 synchronized (cacheMap) 175 { 176 running = false; 177 timeoutTask.interrupt(); 178 cacheMap.clear(); 179 try 180 { 181 pm.destroy(); 182 } 183 catch (Exception e) 184 { 185 throw new RuntimeException (e); 186 } 187 } 188 } 189 190 protected void passivate(StatefulBeanContext ctx) 191 { 192 ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); 193 try 194 { 195 Thread.currentThread().setContextClassLoader(((EJBContainer) ctx.getContainer()).getClassloader()); 196 pm.passivateSession(ctx); 197 } 198 finally 199 { 200 Thread.currentThread().setContextClassLoader(oldCl); 201 } 202 } 203 204 public StatefulBeanContext create() 205 { 206 StatefulBeanContext ctx = null; 207 try 208 { 209 ctx = (StatefulBeanContext) pool.get(); 210 synchronized (cacheMap) 211 { 212 cacheMap.put(ctx.getId(), ctx); 213 } 214 ctx.inUse = true; 215 ctx.lastUsed = System.currentTimeMillis(); 216 } 217 catch (EJBException e) 218 { 219 e.printStackTrace(); 220 throw e; 221 } 222 catch (Exception e) 223 { 224 e.printStackTrace(); 225 throw new EJBException (e); 226 } 227 return ctx; 228 } 229 230 public StatefulBeanContext create(Class [] initTypes, Object [] initValues) 231 { 232 StatefulBeanContext ctx = null; 233 try 234 { 235 ctx = (StatefulBeanContext) pool.get(initTypes, initValues); 236 synchronized (cacheMap) 237 { 238 cacheMap.put(ctx.getId(), ctx); 239 } 240 ctx.inUse = true; 241 ctx.lastUsed = System.currentTimeMillis(); 242 } 243 catch (EJBException e) 244 { 245 e.printStackTrace(); 246 throw e; 247 } 248 catch (Exception e) 249 { 250 e.printStackTrace(); 251 throw new EJBException (e); 252 } 253 return ctx; 254 } 255 256 public StatefulBeanContext get(Object key) throws EJBException 257 { 258 StatefulBeanContext entry = null; 259 synchronized (cacheMap) 260 { 261 entry = (StatefulBeanContext) cacheMap.get(key); 262 } 263 if (entry == null) 264 { 265 Object bean = pm.activateSession(key); 266 if (bean == null) 267 { 268 throw new NoSuchEJBException ("Could not find Stateful bean: " + key); 269 } 270 entry = (StatefulBeanContext) bean; 271 synchronized (cacheMap) 272 { 273 cacheMap.put(key, entry); 274 } 275 } 276 entry.inUse = true; 277 entry.lastUsed = System.currentTimeMillis(); 278 return entry; 279 } 280 281 public void finished(StatefulBeanContext ctx) 282 { 283 synchronized (ctx) 284 { 285 ctx.inUse = false; 286 ctx.lastUsed = System.currentTimeMillis(); 287 if (ctx.markedForPassivation) 288 { 289 passivate(ctx); 290 } 291 } 292 } 293 294 public void remove(Object key) 295 { 296 StatefulBeanContext ctx = null; 297 synchronized (cacheMap) 298 { 299 ctx = (StatefulBeanContext) cacheMap.remove(key); 300 } 301 if (ctx != null) pool.remove(ctx); 302 } 303 304 305 } 306 | Popular Tags |