1 28 29 package com.caucho.transaction; 30 31 import com.caucho.config.types.Period; 32 import com.caucho.loader.ClassLoaderListener; 33 import com.caucho.loader.DynamicClassLoader; 34 import com.caucho.loader.Environment; 35 import com.caucho.log.Log; 36 import com.caucho.transaction.xalog.AbstractXALogManager; 37 import com.caucho.transaction.xalog.AbstractXALogStream; 38 import com.caucho.util.Crc64; 39 import com.caucho.util.L10N; 40 import com.caucho.util.RandomUtil; 41 42 import javax.transaction.*; 43 import javax.transaction.xa.XAException ; 44 import javax.transaction.xa.XAResource ; 45 import javax.transaction.xa.Xid ; 46 import java.io.Serializable ; 47 import java.lang.ref.WeakReference ; 48 import java.util.ArrayList ; 49 import java.util.logging.Level ; 50 import java.util.logging.Logger ; 51 52 55 public class TransactionManagerImpl 56 implements TransactionManager, Serializable , 57 ClassLoaderListener { 58 private static L10N L = new L10N(TransactionManagerImpl.class); 59 private static Logger log = Log.open(TransactionManagerImpl.class); 60 61 private static TransactionManagerImpl _tm = new TransactionManagerImpl(); 62 63 private int _serverId; 64 65 private AbstractXALogManager _xaLogManager; 66 67 private ThreadLocal <TransactionImpl> _threadTransaction 69 = new ThreadLocal <TransactionImpl>(); 70 71 private ArrayList <WeakReference <TransactionImpl>> _transactionList 72 = new ArrayList <WeakReference <TransactionImpl>>(); 73 74 private ArrayList <TransactionListener> _transactionListeners 76 = new ArrayList <TransactionListener>(); 77 78 private long _timeout = -1; 79 80 public TransactionManagerImpl() 81 { 82 } 83 84 87 public static TransactionManagerImpl getInstance() 88 { 89 return _tm; 90 } 91 92 95 public static TransactionManagerImpl getLocal() 96 { 97 return _tm; 98 } 99 100 103 public void setTimeout(Period timeout) 104 { 105 _timeout = timeout.getPeriod(); 106 } 107 108 111 public long getTimeout() 112 { 113 return _timeout; 114 } 115 116 119 public void setXALogManager(AbstractXALogManager xaLogManager) 120 { 121 _xaLogManager = xaLogManager; 122 } 123 124 127 public void begin() 128 throws NotSupportedException, SystemException 129 { 130 getCurrent().begin(); 131 } 132 133 136 XidImpl createXID() 137 { 138 return new XidImpl(getServerId(), 139 RandomUtil.getRandomLong()); 140 } 141 144 AbstractXALogStream getXALogStream() 145 { 146 if (_xaLogManager != null) 147 return _xaLogManager.getStream(); 148 else 149 return null; 150 } 151 152 155 private int getServerId() 156 { 157 if (_serverId == 0) { 158 String server = (String ) Environment.getAttribute("caucho.server-id"); 159 160 if (server == null) 161 _serverId = 1; 162 else 163 _serverId = (int) Crc64.generate(server); 164 } 165 166 return _serverId; 167 } 168 169 172 public Transaction getTransaction() 173 throws SystemException 174 { 175 TransactionImpl trans = _threadTransaction.get(); 176 177 if (trans == null || 178 trans.getStatus() == Status.STATUS_NO_TRANSACTION || 179 trans.getStatus() == Status.STATUS_UNKNOWN || 180 trans.isSuspended()) 181 return null; 182 else { 183 return trans; 184 } 185 } 186 187 190 public Transaction suspend() 191 throws SystemException 192 { 193 TransactionImpl trans = _threadTransaction.get(); 194 195 if (trans == null || 196 (! trans.hasResources() && 197 (trans.getStatus() == Status.STATUS_NO_TRANSACTION || 198 trans.getStatus() == Status.STATUS_UNKNOWN))) 199 return null; 200 201 _threadTransaction.set(null); 202 trans.suspend(); 203 204 return trans; 205 } 206 207 210 public void resume(Transaction tobj) 211 throws InvalidTransactionException, SystemException 212 { 213 Transaction old = _threadTransaction.get(); 214 215 if (old != null && old.getStatus() != Status.STATUS_NO_TRANSACTION) 216 throw new SystemException(L.l("can't resume transaction with active transaction {0}", String.valueOf(old))); 217 218 TransactionImpl impl = (TransactionImpl) tobj; 219 220 impl.resume(); 221 222 _threadTransaction.set(impl); 223 } 224 225 228 public void setRollbackOnly() 229 throws SystemException 230 { 231 getCurrent().setRollbackOnly(); 232 } 233 234 237 public int getStatus() 238 throws SystemException 239 { 240 return getCurrent().getStatus(); 241 } 242 243 246 public void setTransactionTimeout(int seconds) 247 throws SystemException 248 { 249 getCurrent().setTransactionTimeout(seconds); 250 } 251 252 255 public void commit() 256 throws RollbackException, HeuristicMixedException, 257 HeuristicRollbackException, SystemException 258 { 259 getCurrent().commit(); 260 } 261 262 265 public void rollback() 266 { 267 getCurrent().rollback(); 268 } 269 270 273 279 280 286 public TransactionImpl getCurrent() 287 { 288 TransactionImpl trans = _threadTransaction.get(); 289 290 if (trans == null || trans.isDead()) { 291 trans = new TransactionImpl(this); 292 _threadTransaction.set(trans); 293 294 addTransaction(trans); 295 } 296 297 return trans; 298 } 299 300 private void addTransaction(TransactionImpl trans) 301 { 302 synchronized (_transactionList) { 303 for (int i = _transactionList.size() - 1; i >= 0; i--) { 304 WeakReference <TransactionImpl> ref = _transactionList.get(i); 305 306 if (ref.get() == null) 307 _transactionList.remove(i); 308 } 309 310 _transactionList.add(new WeakReference <TransactionImpl>(trans)); 311 } 312 } 313 314 317 public void recover(XAResource xaRes) 318 throws XAException 319 { 320 Xid []xids; 321 322 xids = xaRes.recover(XAResource.TMSTARTRSCAN|XAResource.TMENDRSCAN); 323 324 if (xids == null) 325 return; 326 327 for (int i = 0; i < xids.length; i++) { 328 byte []global = xids[i].getGlobalTransactionId(); 329 330 if (global.length != XidImpl.GLOBAL_LENGTH) 331 continue; 332 333 XidImpl xidImpl = new XidImpl(xids[i].getGlobalTransactionId()); 334 335 if (_xaLogManager != null && 336 _xaLogManager.hasCommittedXid(xidImpl)) { 337 log.fine(L.l("XAResource {0} commit xid {1}", xaRes, xidImpl)); 338 339 try { 340 xaRes.commit(xidImpl, false); 341 } catch (Throwable e) { 342 log.log(Level.WARNING, e.toString(), e); 343 } 344 } 345 else { 346 349 log.fine(L.l("XAResource {0} forget xid {1}", xaRes, xidImpl)); 350 351 try { 352 xaRes.forget(xidImpl); 353 } catch (Throwable e) { 354 log.log(Level.WARNING, e.toString(), e); 355 } 356 } 357 } 358 } 359 360 363 public void flush() 364 { 365 if (_xaLogManager != null) 366 _xaLogManager.flush(); 367 } 368 369 372 public void classLoaderInit(DynamicClassLoader loader) 373 { 374 } 375 376 379 public void classLoaderDestroy(DynamicClassLoader loader) 380 { 381 AbstractXALogManager xaLogManager = _xaLogManager; 382 _xaLogManager = null; 383 384 if (xaLogManager != null) 385 xaLogManager.close(); 386 387 _serverId = 0; 388 389 synchronized (_transactionList) { 390 for (int i = _transactionList.size() - 1; i >= 0; i--) { 391 WeakReference <TransactionImpl> ref = _transactionList.get(i); 392 TransactionImpl xa = ref.get(); 393 394 try { 395 if (xa != null) { 396 xa.rollback(); 397 } 398 } catch (Throwable e) { 399 log.log(Level.WARNING, e.toString(), e); 400 } 401 } 402 } 403 } 404 405 408 public void testClear() 409 { 410 _serverId = 0; 411 _timeout = -1; 412 AbstractXALogManager logManager = _xaLogManager; 413 _xaLogManager = null; 414 415 if (logManager != null) 416 logManager.close(); 417 } 418 419 public String toString() 420 { 421 return "TransactionManagerImpl[]"; 422 } 423 } 424 | Popular Tags |