| 1 21 22 package com.rift.coad.lib.bean; 24 25 import java.util.ArrayList ; 27 import java.util.Date ; 28 import java.util.HashMap ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Map ; 32 import java.util.Vector ; 33 import java.util.concurrent.ConcurrentHashMap ; 34 import javax.rmi.PortableRemoteObject ; 35 import javax.transaction.xa.XAException ; 36 import javax.transaction.xa.XAResource ; 37 import javax.transaction.xa.Xid ; 38 39 import org.apache.log4j.Logger; 41 42 import com.rift.coad.lib.cache.Cache; 44 import com.rift.coad.lib.cache.CacheEntry; 45 import com.rift.coad.lib.common.RandomGuid; 46 import com.rift.coad.lib.configuration.ConfigurationFactory; 47 import com.rift.coad.lib.configuration.Configuration; 48 import com.rift.coad.lib.thread.ThreadStateMonitor; 49 import com.rift.coad.util.lock.LockRef; 50 import com.rift.coad.util.lock.ObjectLockFactory; 51 import com.rift.coad.util.transaction.TransactionManager; 52 53 54 59 public class TransactionProxyCache implements Cache,XAResource { 60 61 64 public class ChangeEntry { 65 private Xid transactionId = null; 67 private List newEntries = new ArrayList (); 68 69 70 75 public ChangeEntry(Xid transactionId) { 76 this.transactionId = transactionId; 77 } 78 79 80 85 public Xid getTransactionId() { 86 return transactionId; 87 } 88 89 90 95 public void addEntry(ProxyCacheEntry entry) { 96 newEntries.add(entry); 97 } 98 99 100 103 public List getEntries() { 104 return newEntries; 105 } 106 } 107 108 private final static String CACHE_EXPIRY_TIME = "proxy_cache_expiry"; 110 private final static long CACHE_EXPIRY_TIME_DEFAULT = 60 * 1000; 111 112 protected static Logger log = 114 Logger.getLogger(ProxyCache.class.getName()); 115 116 private ThreadLocal currentTransaction = new ThreadLocal (); 118 private ThreadStateMonitor status = new ThreadStateMonitor(); 119 private Map cacheEntries = new ConcurrentHashMap (); 120 private long defaultCacheExpiryTime = 0; 121 private Map transactionChanges = new ConcurrentHashMap (); 122 123 124 127 public TransactionProxyCache() throws BeanException { 128 try { 129 Configuration config = ConfigurationFactory.getInstance(). 130 getConfig(ProxyCache.class); 131 defaultCacheExpiryTime = config.getLong(CACHE_EXPIRY_TIME, 132 CACHE_EXPIRY_TIME_DEFAULT); 133 } catch (Exception ex) { 134 log.error("Failed to start the TransactionProxyCache object " + 135 "because : " + ex.getMessage(),ex); 136 throw new BeanException( 137 "Failed to start the TransactionProxyCache object " + 138 "because : " + ex.getMessage(),ex); 139 } 140 } 141 142 143 146 public void garbageCollect() { 147 Map cacheEntries = new HashMap (); 148 cacheEntries.putAll(this.cacheEntries); 149 150 Date currentTime = new Date (); 152 for (Iterator iter = cacheEntries.keySet().iterator(); 153 iter.hasNext();) { 154 Object key = iter.next(); 155 ProxyCacheEntry cacheEntry = 156 (ProxyCacheEntry)cacheEntries.get(key); 157 if (cacheEntry.isExpired(currentTime)) { 158 synchronized(this.cacheEntries) { 159 this.cacheEntries.remove(key); 160 } 161 cacheEntry.cacheRelease(); 162 } 163 } 164 } 165 166 167 170 public void clear() { 171 LockRef lockRef = null; 172 try { 173 lockRef = ObjectLockFactory.getInstance().acquireReadLock(this); 174 Map cacheEntries = new HashMap (); 175 status.terminate(false); 176 cacheEntries.putAll(this.cacheEntries); 177 this.cacheEntries.clear(); 178 179 for (Iterator iter = cacheEntries.keySet().iterator(); 180 iter.hasNext();) { 181 ProxyCacheEntry cacheEntry = 182 (ProxyCacheEntry)cacheEntries.get(iter.next()); 183 try { 184 cacheEntry.cacheRelease(); 185 } catch (Exception ex) { 186 log.error("Failed to release the cache entry : " + 187 ex.getMessage(),ex); 188 } 189 } 190 } catch (Exception ex) { 191 log.error("Failed clear the cache : " + ex.getMessage(),ex); 192 } finally { 193 try { 194 if (lockRef != null) { 195 lockRef.release(); 196 } 197 } catch (Exception ex) { 198 log.error("Failed to release the lock : " + 199 ex.getMessage(),ex); 200 } 201 } 202 } 203 204 205 212 public void addCacheEntry(long timeout, Object proxy, CacheEntry handler) 213 throws BeanException { 214 try { 215 checkStatus(); 216 TransactionManager.getInstance().bindResource(this,false); 217 long cacheTimeout = timeout; 218 if (timeout == -1) { 219 cacheTimeout = defaultCacheExpiryTime; 220 } 221 ProxyCacheEntry newEntry = new ProxyCacheEntry(timeout, 222 proxy, handler); 223 ChangeEntry changeEntry = (ChangeEntry)transactionChanges.get( 224 currentTransaction.get()); 225 changeEntry.addEntry(newEntry); 226 } catch (Exception ex) { 227 log.error("Failed to add the cache entry : " + 228 ex.getMessage(),ex); 229 throw new BeanException("Failed to add the cache entry : " + 230 ex.getMessage(),ex); 231 } 232 } 233 234 235 241 public boolean contains(Object cacheEntry) { 242 if (!status.isTerminated()) { 243 return cacheEntries.containsKey(cacheEntry); 244 } 245 return false; 246 } 247 248 249 256 public void commit(Xid xid, boolean b) throws XAException { 257 try { 258 ChangeEntry changeEntry = (ChangeEntry)transactionChanges.get(xid); 259 List entries = changeEntry.getEntries(); 260 for (Iterator iter = entries.iterator(); iter.hasNext();) { 261 ProxyCacheEntry proxyCacheEntry = (ProxyCacheEntry)iter.next(); 262 cacheEntries.put(proxyCacheEntry.getCacheEntry(), 263 proxyCacheEntry); 264 } 265 } catch (Exception ex) { 266 log.error("Failed to commit the changes : " + ex.getMessage(),ex); 267 throw new XAException ("Failed to commit the changes : " + 268 ex.getMessage()); 269 } 270 } 271 272 273 280 public void end(Xid xid, int i) throws XAException { 281 } 282 283 284 290 public void forget(Xid xid) throws XAException { 291 try { 292 transactionChanges.remove(xid); 293 } catch (Exception ex) { 294 log.error("Failed to forget the changes : " + ex.getMessage(),ex); 295 throw new XAException ("Failed to forget the changes : " + 296 ex.getMessage()); 297 } 298 } 299 300 301 307 public int getTransactionTimeout() throws XAException { 308 return -1; 309 } 310 311 312 320 public boolean isSameRM(XAResource xAResource) throws XAException { 321 return this == xAResource; 322 } 323 324 325 332 public int prepare(Xid xid) throws XAException { 333 return XAResource.XA_OK; 334 } 335 336 337 345 public Xid [] recover(int i) throws XAException { 346 return null; 347 } 348 349 350 356 public void rollback(Xid xid) throws XAException { 357 try { 358 ChangeEntry changeEntry = (ChangeEntry)transactionChanges.get(xid); 359 List entries = changeEntry.getEntries(); 360 for (Iterator iter = entries.iterator(); iter.hasNext();) { 361 ProxyCacheEntry proxyCacheEntry = (ProxyCacheEntry)iter.next(); 362 try { 363 proxyCacheEntry.cacheRelease(); 364 } catch (Exception ex) { 365 log.error("Failed to release the entry"); 366 } 367 } 368 transactionChanges.remove(xid); 369 } catch (Exception ex) { 370 log.error("Failed to rollback the changes : " + ex.getMessage(),ex); 371 throw new XAException ("Failed to rollback the changes : " + 372 ex.getMessage()); 373 } 374 } 375 376 383 public boolean setTransactionTimeout(int i) throws XAException { 384 return true; 385 } 386 387 388 395 public void start(Xid xid, int i) throws XAException { 396 if (!transactionChanges.containsKey(xid)) { 397 transactionChanges.put(xid,new ChangeEntry(xid)); 398 } 399 currentTransaction.set(xid); 400 } 401 402 407 private void checkStatus() throws BeanException { 408 if (status.isTerminated()) { 409 throw new BeanException("The proxy cache has been shut down."); 410 } 411 } 412 } 413 | Popular Tags |