1 package org.jboss.cache.transaction; 2 3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 6 import javax.naming.Context ; 7 import javax.naming.InitialContext ; 8 import javax.naming.NamingException ; 9 import javax.transaction.HeuristicMixedException ; 10 import javax.transaction.HeuristicRollbackException ; 11 import javax.transaction.InvalidTransactionException ; 12 import javax.transaction.NotSupportedException ; 13 import javax.transaction.RollbackException ; 14 import javax.transaction.SystemException ; 15 import javax.transaction.Transaction ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.Map ; 19 import java.util.Properties ; 20 21 public class AsyncRollbackTransactionManager extends DummyTransactionManager 22 { 23 static AsyncRollbackTransactionManager instance = null; 24 private static Log log = LogFactory.getLog(AsyncRollbackTransactionManager.class); 25 26 public static DummyTransactionManager getInstance() 27 { 28 if (instance == null) 29 { 30 instance = new AsyncRollbackTransactionManager(); 31 try 32 { 33 Properties p = new Properties (); 34 p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory"); 35 Context ctx = new InitialContext (p); 36 ctx.bind("java:/TransactionManager", instance); 37 ctx.bind("UserTransaction", new DummyUserTransaction(instance)); 38 } 39 catch (NamingException e) 40 { 41 log.error("binding of DummyTransactionManager failed", e); 42 } 43 } 44 return instance; 45 } 46 47 private Thread timedOutTransactionsChecker = null; 48 private int timeout = 30; 49 private Map txMap = new HashMap (); 50 51 public void setTransactionTimeout(int seconds) throws SystemException 52 { 53 this.timeout = seconds; 54 } 55 56 public AsyncRollbackTransactionManager() 57 { 58 timedOutTransactionsChecker = new TimedOutTransactionsChecker(); 59 timedOutTransactionsChecker.start(); 60 } 61 62 private class TimedOutTransactionsChecker extends Thread 63 { 64 private boolean running; 65 66 public TimedOutTransactionsChecker() 67 { 68 } 69 70 public void run() 71 { 72 running = true; 73 while (running) 74 { 75 try 76 { 77 Thread.sleep(500); 78 synchronized (this) 79 { 80 Iterator iterator = txMap.values().iterator(); 81 do 82 { 83 if (!iterator.hasNext()) 84 { 85 break; 86 } 87 AsyncRollbackTransaction t = (AsyncRollbackTransaction) iterator.next(); 88 try 89 { 90 t.wakeUp(); 91 } 92 catch (SystemException e) 93 { 94 e.printStackTrace(); 95 } 96 97 } 98 while (true); 99 } 100 } 101 catch (InterruptedException e) 102 { 103 } 104 } 105 } 106 107 } 108 109 public void begin() throws NotSupportedException , SystemException 110 { 111 Transaction currentTx; 112 if ((currentTx = getTransaction()) != null) 113 { 114 throw new NotSupportedException (Thread.currentThread() + 115 " is already associated with a transaction (" + currentTx + ")"); 116 } 117 AsyncRollbackTransaction tx = new AsyncRollbackTransaction(this, timeout); 118 setTransaction(tx); 119 txMap.put(new Long (tx.generateTransactionId()), tx); 120 } 121 122 123 public void rollback() throws IllegalStateException , SecurityException , SystemException 124 { 125 removeTxFromMap((AsyncRollbackTransaction) getTransaction()); 126 super.rollback(); 127 } 128 129 public void removeTxFromMap(AsyncRollbackTransaction tx) throws SystemException 130 { 131 if (tx != null) 132 { 133 txMap.remove(new Long (tx.getTransactionId())); 134 } 135 } 136 137 138 public void commit() throws RollbackException , HeuristicMixedException , HeuristicRollbackException , SecurityException , IllegalStateException , SystemException 139 { 140 AsyncRollbackTransaction tx = (AsyncRollbackTransaction) getTransaction(); 141 if (tx != null) 142 { 143 txMap.remove(new Long (tx.getTransactionId())); 144 } 145 super.commit(); 146 } 147 148 149 public void resume(Transaction tx) throws InvalidTransactionException , IllegalStateException , SystemException 150 { 151 super.resume(tx); 153 } 154 155 156 public Transaction suspend() throws SystemException 157 { 158 return super.suspend(); 160 } 161 162 static class AsyncRollbackTransaction extends DummyTransaction 163 { 164 private static long transactionNums = 0; 165 166 private long transactionId; 167 168 private long beginTimeMillis; 169 170 private int timeoutSec; 171 172 public AsyncRollbackTransaction(DummyBaseTransactionManager tm, int timeout) 173 { 174 super(tm); 175 this.timeoutSec = timeout; 176 this.beginTimeMillis = System.currentTimeMillis(); 177 } 178 179 182 public long getTransactionId() 183 { 184 return transactionId; 185 } 186 187 public long generateTransactionId() 188 { 189 long result = 0; 190 synchronized (AsyncRollbackTransaction.class) 191 { 192 transactionNums++; 193 result = transactionNums; 194 } 195 this.transactionId = result; 196 return result; 197 } 198 199 final int getTimeoutSeconds() 200 { 201 return timeoutSec; 202 } 203 204 protected final void asyncRollback() throws SystemException 205 { 206 Thread asyncRollbackThread = new Thread () 207 { 208 public void run() 209 { 210 try 211 { 212 rollback(); 213 } 214 catch (Exception exception) 215 { 216 } 217 } 218 }; 219 ((AsyncRollbackTransactionManager) tm_).removeTxFromMap(this); 220 asyncRollbackThread.start(); 221 } 222 223 public void wakeUp() throws SystemException 224 { 225 if (isTransactionTimedOut()) 226 { 227 asyncRollback(); 228 } 229 } 230 231 private boolean isTransactionTimedOut() 232 { 233 return (System.currentTimeMillis() - beginTimeMillis) > (timeoutSec * 1000); 234 } 235 } 236 237 238 } | Popular Tags |