KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > distributedtx > J2EETransactionManagerOpt


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.distributedtx;
24
25 import java.util.*;
26 import javax.transaction.*;
27 import javax.transaction.xa.*;
28
29 import com.sun.enterprise.ComponentInvocation;
30 import com.sun.enterprise.resource.*;
31 import com.sun.enterprise.util.i18n.StringManager;
32
33 //START OF IASRI 4660742
34
import java.util.logging.*;
35 import com.sun.logging.*;
36 //END OF IASRI 4660742
37

38
39
40 /**
41  * A wrapper over J2EETransactionManagerImpl that provides optimized local
42  * transaction support when a transaction uses zero/one non-XA resource,
43  * and delegates to J2EETransactionManagerImpl (i.e. JTS) otherwise.
44  *
45  * @author Tony Ng
46  */

47 public final class J2EETransactionManagerOpt
48          extends J2EETransactionManagerImpl
49 {
50
51     // START OF IASRI 4660742
52
static Logger _logger=LogDomains.getLogger(LogDomains.JTA_LOGGER);
53     // END OF IASRI 4660742
54
// Sting Manager for Localization
55
private static StringManager sm = StringManager.getManager(J2EETransactionManagerOpt.class);
56     // Note: this is not inheritable because we dont want transactions
57
// to be inherited by child threads.
58
private ThreadLocal JavaDoc transactions;
59     private ThreadLocal JavaDoc localCallCounter;
60     private Hashtable globalTransactions;
61     // START IASRI 4662745
62
private static com.sun.jts.CosTransactions.RWLock freezeLock = new com.sun.jts.CosTransactions.RWLock();
63     // END IASRI 4662745
64

65     public J2EETransactionManagerOpt() {
66         super();
67     transactions = new ThreadLocal JavaDoc();
68     localCallCounter = new ThreadLocal JavaDoc();
69     globalTransactions = new Hashtable();
70     }
71
72     public void clearThreadTx() {
73     transactions.set(null);
74     }
75
76 /****************************************************************************/
77 /** Implementations of J2EETransactionManager APIs **************************/
78 /****************************************************************************/
79
80     public boolean enlistResource(Transaction tran, ResourceHandle h)
81         throws RollbackException, IllegalStateException JavaDoc, SystemException
82     {
83         if ( !h.isTransactional() )
84         return true;
85
86         //If LazyEnlistment is suspended, do not enlist resource.
87
if(h.isEnlistmentSuspended()){
88             return false;
89         }
90
91     if ( !(tran instanceof J2EETransaction) )
92         return super.enlistResource(tran, h);
93
94     J2EETransaction tx = (J2EETransaction)tran;
95
96       if(_logger.isLoggable(Level.FINE)) {
97            _logger.log(Level.FINE,"\n\nIn J2EETransactionManagerOpt.enlistResource, h=" +h+" h.xares="+h.getXAResource()+" h.alloc="
98                +h.getResourceAllocator()+" tx="+tx);
99       }
100
101     if ( (tx.getNonXAResource()!=null) && (!useLAO || (useLAO && !h.supportsXA()))) {
102         boolean isSameRM=false;
103         try {
104             isSameRM = h.getXAResource().isSameRM(tx.getNonXAResource().getXAResource());
105         } catch ( XAException xex ) {
106             throw new SystemException(sm.getString("enterprise_distributedtx.samerm_excep",xex));
107         } catch ( Exception JavaDoc ex ) {
108             throw new SystemException(sm.getString("enterprise_distributedtx.samerm_excep",ex));
109         }
110         if ( !isSameRM ) {
111             throw new IllegalStateException JavaDoc(sm.getString("enterprise_distributedtx.already_has_nonxa"));
112         }
113     }
114
115     if (monitoringEnabled) {
116         tx.addResourceName(h.getResourceSpec().getResourceId());
117     }
118
119     if ( h.supportsXA() ) {
120         if ( tx.isLocalTx() ) {
121         startJTSTx(tx);
122         //If transaction conatains a NonXA and no LAO, convert the existing
123
//Non XA to LAO
124
if(useLAO) {
125             if(tx.getNonXAResource()!=null && (tx.getLAOResource()==null) ) {
126                 tx.setLAOResource(tx.getNonXAResource());
127                 super.enlistLAOResource(tx, tx.getNonXAResource());
128             }
129         }
130         }
131         return super.enlistResource(tx, h);
132     }
133     else { // non-XA resource
134
if (tx.isImportedTransaction())
135                 throw new IllegalStateException JavaDoc(sm.getString("enterprise_distributedtx.nonxa_usein_jts"));
136             if (tx.getNonXAResource() == null) {
137             tx.setNonXAResource(h);
138             }
139         if ( tx.isLocalTx() ) {
140         // notify resource that it is being used for tx,
141
// e.g. this allows the correct physical connection to be
142
// swapped in for the logical connection.
143
// The flags parameter can be 0 because the flags are not
144
// used by the XAResource implementation for non-XA resources.
145
try {
146             h.getXAResource().start(tx.getLocalXid(), 0);
147         } catch ( XAException ex ) {
148             throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.xaresource_start_excep"),ex);
149         }
150
151         poolmgr.resourceEnlisted(tx, h);
152         return true;
153         }
154         else {
155         if(useLAO) {
156             return super.enlistResource(tx, h);
157         }
158         else {
159             throw new IllegalStateException JavaDoc(sm.getString("enterprise_distributedtx.nonxa_usein_jts"));
160         }
161         }
162     }
163     }
164
165     void startJTSTx(J2EETransaction tx)
166         throws RollbackException, IllegalStateException JavaDoc, SystemException
167     {
168         try {
169             if (tx.isAssociatedTimeout()) {
170                 // calculate the timeout for the transaction, this is required as the local tx
171
// is getting converted to a global transaction
172
int timeout = tx.cancelTimerTask();
173                 int newtimeout = (int) ((System.currentTimeMillis() - tx.getStartTime()) / 1000);
174                 newtimeout = (timeout - newtimeout);
175                 super.begin(newtimeout);
176             }
177             else {
178                 super.begin();
179             }
180             // START IASRI 4662745
181
// The local Transaction was promoted to global Transaction
182
if (tx!=null && monitoringEnabled){
183                 if(activeTransactions.remove(tx)){
184                     m_transInFlight--;
185                 }
186             }
187             // END IASRI 4662745
188
} catch ( NotSupportedException ex ) {
189         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.lazy_transaction_notstarted"),ex);
190     }
191     Transaction jtsTx = super.getTransaction();
192     tx.setJTSTx(jtsTx);
193     jtsTx.registerSynchronization(new JTSSynchronization(jtsTx, this));
194     globalTransactions.put(jtsTx, tx);
195     }
196
197     public boolean delistResource(Transaction tran, ResourceHandle h, int flag)
198         throws IllegalStateException JavaDoc, SystemException
199     {
200         if (!h.isTransactional()) return true;
201     if ( !(tran instanceof J2EETransaction) )
202         return super.delistResource(tran, h, flag);
203
204     J2EETransaction tx = (J2EETransaction)tran;
205     if ( tx.isLocalTx() ) {
206         // dissociate resource from tx
207
try {
208         h.getXAResource().end(tx.getLocalXid(), flag);
209         } catch ( XAException ex ) {
210         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.xaresource_end_excep", ex));
211         }
212         return true;
213     }
214     else
215         return super.delistResource(tx, h, flag);
216     }
217
218
219     /**
220      * Called from the CORBA Interceptors on the server-side when
221      * the server is replying to the client (local + remote client).
222      * Check if there is an active transaction and remove it from TLS.
223      */

224     public void checkTransactionImport() {
225     // First check if this is a local call
226
int[] count = (int[])localCallCounter.get();
227     if ( count != null && count[0] > 0 ) {
228         count[0]--;
229         return;
230     }
231     else {
232         // A remote call, clear TLS so that if this thread is reused
233
// later, the current tx doesnt hang around.
234
clearThreadTx();
235     }
236     }
237
238     /**
239      * Called from the CORBA Interceptors on the client-side when
240      * a client makes a call to a remote object (not in the same JVM).
241      * Check if there is an active, exportable transaction.
242      * @exception RuntimeException if the transaction is not exportable
243      */

244     public void checkTransactionExport(boolean isLocal) {
245
246     if ( isLocal ) {
247         // Put a counter in TLS indicating this is a local call.
248
// Use int[1] as a mutable java.lang.Integer!
249
int[] count = (int[])localCallCounter.get();
250         if ( count == null ) {
251         count = new int[1];
252         localCallCounter.set(count);
253         }
254         count[0]++;
255         return;
256     }
257
258         J2EETransaction tx = (J2EETransaction)transactions.get();
259     if ( tx == null )
260         return;
261
262     if ( !tx.isLocalTx() ) // a JTS tx, can be exported
263
return;
264
265     // Check if a local tx with non-XA resource is being exported.
266
// XXX what if this is a call on a non-transactional remote object ?
267
if ( tx.getNonXAResource() != null )
268         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.cannot_export_transaction_having_nonxa"));
269
270     // If we came here, it means we have a local tx with no registered
271
// resources, so start a JTS tx which can be exported.
272
try {
273         startJTSTx(tx);
274     } catch ( RollbackException rlex ) {
275         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.unable_tostart_JTSTransaction"),rlex);
276     } catch ( IllegalStateException JavaDoc isex ) {
277         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.unable_tostart_JTSTransaction"),isex);
278     } catch ( SystemException ex ) {
279         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.unable_tostart_JTSTransaction"),ex);
280     } catch ( Exception JavaDoc excep ) {
281         throw new RuntimeException JavaDoc(sm.getString("enterprise_distributedtx.unable_tostart_JTSTransaction"),excep);
282     }
283     }
284
285
286 /****************************************************************************/
287 /** Implementations of JTA TransactionManager APIs **************************/
288 /****************************************************************************/
289
290    // Implementation of begin() is moved to begin(int timeout)
291
public void begin() throws NotSupportedException, SystemException {
292     begin(getEffectiveTimeout());
293    }
294
295    /**
296     * This method is introduced as part of implementing the local transaction timeout
297     * capability. Implementation of begin() moved here. Previpusly there is no timeout
298     * infrastructure for local txns, so when ever a timeout required for local txn, it
299     * uses the globaltxn timeout infrastructure by doing an XA simulation.
300     **/

301    public void begin(int timeout) throws NotSupportedException, SystemException {
302     // Check if tx already exists
303
if ( transactions.get() != null )
304         throw new NotSupportedException(sm.getString("enterprise_distributedtx.notsupported_nested_transaction"));
305
306     // Check if JTS tx exists, without starting JTS tx.
307
// This is needed in case the JTS tx was imported from a client.
308
if ( super.getStatus() != Status.STATUS_NO_TRANSACTION )
309         throw new NotSupportedException(sm.getString("enterprise_distributedtx.notsupported_nested_transaction"));
310             // START IASRI 4662745
311
boolean acquiredlock = false;
312         if(monitoringEnabled){
313              freezeLock.acquireReadLock();
314              acquiredlock = true;
315         }
316         try{
317             J2EETransaction tx = null;
318             if (timeout > 0)
319                 tx = new J2EETransaction(timeout);
320             else
321                 tx = new J2EETransaction();
322             transactions.set(tx);
323             if (monitoringEnabled) {
324                 activeTransactions.addElement(tx);
325                 m_transInFlight++;
326                 ComponentInvocation inv = invMgr.getCurrentInvocation();
327                 if (inv != null && inv.getInstance() != null) {
328                     tx.setComponentName(inv.getInstance().getClass().getName());
329                 }
330             }
331         }finally{
332             if(acquiredlock){
333                 freezeLock.releaseReadLock();
334             }
335         }
336             // START IASRI 4662745
337
}
338
339     public void commit() throws RollbackException,
340     HeuristicMixedException, HeuristicRollbackException, SecurityException JavaDoc,
341     IllegalStateException JavaDoc, SystemException {
342
343     try {
344             J2EETransaction tx = (J2EETransaction)transactions.get();
345         if ( tx != null && tx.isLocalTx()) {
346                 // START IASRI 4662745
347
Object JavaDoc obj = null;
348                 boolean acquiredlock = false;
349                 if(monitoringEnabled){
350                     obj = tx;
351                 }
352                 try{
353                     if(monitoringEnabled){
354                         freezeLock.acquireReadLock();
355                         acquiredlock = true;
356                     }
357                     tx.commit(); // commit local tx
358
if (monitoringEnabled){
359                         monitorTxCompleted(obj, true);
360                     }
361                 }catch(RollbackException e){
362                     if (monitoringEnabled){
363                         monitorTxCompleted(obj, false);
364                     }
365                     throw e;
366                 }catch(HeuristicRollbackException e){
367                     if (monitoringEnabled){
368                         monitorTxCompleted(obj, false);
369                     }
370                     throw e;
371                 }catch(HeuristicMixedException e){
372                     if (monitoringEnabled){
373                         monitorTxCompleted(obj, true);
374                     }
375                     throw e;
376                 }finally{
377                     if(acquiredlock){
378                         freezeLock.releaseReadLock();
379                     }
380                 }
381             }
382         else {
383         super.commit(); // it might be a JTS imported global tx or an error
384
}
385     } finally {
386         transactions.set(null); // clear current thread's tx
387
}
388         // END IASRI 4662745
389
}
390
391     public void rollback() throws IllegalStateException JavaDoc, SecurityException JavaDoc,
392                 SystemException {
393         // START IASRI 4662745
394
boolean acquiredlock=false;
395     try {
396         J2EETransaction tx = (J2EETransaction)transactions.get();
397         if ( tx != null && tx.isLocalTx()) {
398                 Object JavaDoc obj = null;
399                 if(monitoringEnabled){
400                     obj = tx;
401                 }
402                 if(monitoringEnabled){
403                     freezeLock.acquireReadLock();
404                     acquiredlock = true;
405                 }
406         tx.rollback(); // rollback local tx
407
if(monitoringEnabled){
408                     monitorTxCompleted(obj, false);
409                 }
410             }
411         else {
412         super.rollback(); // a JTS imported global tx or an error
413
}
414     } finally {
415         transactions.set(null); // clear current thread's tx
416
if(acquiredlock){
417                 freezeLock.releaseReadLock();
418             }
419     }
420         // END IASRI 4662745
421
}
422
423
424     public int getStatus() throws SystemException {
425     J2EETransaction tx = (J2EETransaction)transactions.get();
426     if ( tx != null && tx.isLocalTx())
427         return tx.getStatus();
428     else
429         return super.getStatus();
430     }
431
432     public Transaction getTransaction() throws SystemException {
433     J2EETransaction tx = (J2EETransaction)transactions.get();
434     if ( tx != null )
435         return tx;
436     else { // maybe a JTS imported tx
437
Transaction jtsTx = super.getTransaction();
438         if ( jtsTx == null )
439         return null;
440         else {
441         // check if this JTS Transaction was previously active
442
// in this JVM (possible for distributed loopbacks).
443
tx = (J2EETransaction)globalTransactions.get(jtsTx);
444         if ( tx == null ) {
445             tx = new J2EETransaction(jtsTx);
446                     tx.setImportedTransaction();
447             try {
448             jtsTx.registerSynchronization(
449                     new JTSSynchronization(jtsTx, this));
450             } catch ( RollbackException rlex ) {
451                 throw new SystemException(rlex.toString());
452             } catch ( IllegalStateException JavaDoc isex ) {
453                 throw new SystemException(isex.toString());
454             } catch ( Exception JavaDoc ex ) {
455                 throw new SystemException(ex.toString());
456             }
457
458             globalTransactions.put(jtsTx, tx);
459         }
460         transactions.set(tx); // associate tx with thread
461
return tx;
462         }
463     }
464     }
465
466     public void setRollbackOnly()
467         throws IllegalStateException JavaDoc, SystemException {
468
469     J2EETransaction tx = (J2EETransaction)transactions.get();
470         // START IASRI 4662745
471
if ( tx != null && tx.isLocalTx()){
472             boolean acquiredlock=false;
473             if(monitoringEnabled){
474                 freezeLock.acquireReadLock();
475                 acquiredlock = true;
476             }
477             try{
478             tx.setRollbackOnly();
479             }finally{
480                 if(acquiredlock){
481                     freezeLock.releaseReadLock();
482                 }
483             }
484         }
485     else
486         super.setRollbackOnly(); // probably a JTS imported tx
487
// END IASRI 4662745
488
}
489
490
491     public Transaction suspend() throws SystemException {
492     J2EETransaction tx = (J2EETransaction)transactions.get();
493     if ( tx != null ) {
494         if ( !tx.isLocalTx() )
495         super.suspend();
496         transactions.set(null);
497         return tx;
498     }
499     else {
500         return super.suspend(); // probably a JTS imported tx
501
}
502     }
503
504     public void resume(Transaction tobj)
505         throws InvalidTransactionException, IllegalStateException JavaDoc,
506             SystemException {
507
508     J2EETransaction tx = (J2EETransaction)transactions.get();
509     if ( tx != null )
510         throw new IllegalStateException JavaDoc(sm.getString("enterprise_distributedtx.transaction_exist_on_currentThread"));
511     if ( tobj instanceof J2EETransaction ) {
512         J2EETransaction j2eeTx = (J2EETransaction)tobj;
513         if ( !j2eeTx.isLocalTx() )
514         super.resume(j2eeTx.getJTSTx());
515
516         transactions.set(tobj);
517     }
518     else {
519         super.resume(tobj); // probably a JTS imported tx
520
}
521     }
522
523     public boolean isTimedOut() {
524         J2EETransaction tx = (J2EETransaction)transactions.get();
525         if ( tx != null)
526         return tx.isTimedout();
527     else
528         return false;
529     }
530     // START IASRI 4662745
531
/*
532     * Called by Admin Framework to freeze the transactions.
533     */

534     public synchronized void freeze(){
535         super.freeze();
536         if(freezeLock.isWriteLocked()){
537             //multiple freezes will hang this thread, therefore just return
538
return;
539         }
540         freezeLock.acquireWriteLock();
541     }
542     /*
543      * Called by Admin Framework to freeze the transactions. These undoes the work done by the freeze.
544      */

545     public synchronized void unfreeze(){
546         super.unfreeze();
547         if(freezeLock.isWriteLocked()){
548             freezeLock.releaseWriteLock();
549         }
550     }
551
552     // END IASRI 4662745
553

554     private class JTSSynchronization implements Synchronization {
555     private Transaction jtsTx;
556     private J2EETransactionManagerOpt j2eeTM;
557
558     JTSSynchronization(Transaction jtsTx, J2EETransactionManagerOpt j2eeTM){
559         this.jtsTx = jtsTx;
560         this.j2eeTM = j2eeTM;
561     }
562
563     public void beforeCompletion() {}
564
565     public void afterCompletion(int status) {
566         j2eeTM.globalTransactions.remove(jtsTx);
567     }
568     }
569 }
570
571
Popular Tags