KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jts > jta > TransactionState


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
24 /*
25  * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
26  * Use is subject to license terms.
27  */

28
29 package com.sun.jts.jta;
30
31 import java.util.*;
32 import javax.transaction.xa.*;
33 import javax.transaction.*;
34 import org.omg.CosTransactions.*;
35 import com.sun.jts.jta.NativeXAResource;
36 import com.sun.jts.jtsxa.XID;
37 import com.sun.jts.jtsxa.OTSResource;
38 import com.sun.jts.jtsxa.OTSResourceImpl;
39 import javax.transaction.SystemException JavaDoc;
40 import javax.transaction.RollbackException JavaDoc;
41 import javax.transaction.Synchronization JavaDoc;
42 import com.sun.jts.jtsxa.Utility;
43 import com.sun.jts.CosTransactions.Configuration;
44 import com.sun.jts.CosTransactions.ControlImpl;
45 import com.sun.jts.CosTransactions.TopCoordinator;
46 import org.omg.CORBA.TRANSACTION_ROLLEDBACK JavaDoc;
47 import com.sun.jts.CosTransactions.GlobalTID;
48
49
50 import java.util.logging.Logger JavaDoc;
51 import java.util.logging.Level JavaDoc;
52 import com.sun.logging.LogDomains;
53 import com.sun.jts.utils.LogFormatter;
54 /**
55  * keep track of per-transaction state
56  *
57  * @author Tony Ng
58  */

59 public class TransactionState {
60
61     /**
62      * various association states for an XAResource
63      */

64     private static final int NOT_EXIST = -1;
65     private static final int ASSOCIATED = 0;
66     private static final int NOT_ASSOCIATED = 1;
67     private static final int ASSOCIATION_SUSPENDED = 2;
68     private static final int FAILED = 3;
69     private static final int ROLLING_BACK = 4;
70
71     private static final Integer JavaDoc NOT_EXIST_INTEGER = new Integer JavaDoc(NOT_EXIST);
72     private static final Integer JavaDoc ASSOCIATED_INTEGER = new Integer JavaDoc(ASSOCIATED);
73     private static final Integer JavaDoc NOT_ASSOCIATED_INTEGER = new Integer JavaDoc(NOT_ASSOCIATED);
74     private static final Integer JavaDoc ASSOCIATION_SUSPENDED_INTEGER = new Integer JavaDoc(ASSOCIATION_SUSPENDED);
75     private static final Integer JavaDoc FAILED_INTEGER = new Integer JavaDoc(FAILED);
76     private static final Integer JavaDoc ROLLING_BACK_INTEGER = new Integer JavaDoc(ROLLING_BACK);
77
78     /**
79      * a mapping of XAResource -> Integer (state)
80      * possible states are listed above
81      */

82     private Map resourceStates;
83
84     /**
85      * Map: XAResource -> Xid
86      */

87     private Map resourceList;
88
89     /**
90      * a set of Xid branches on which xa_start() has been called
91      */

92     private Set seenXids;
93
94     /**
95      * a list of unique resource factory (represented by XAResource)
96      * Vector of XAResource objects
97      */

98     private List factories;
99
100     // the OTS synchronization object for this transaction
101
private SynchronizationImpl syncImpl;
102
103     // count of XAResources that are still in active state
104
// private int activeResources = 0;
105

106     private GlobalTID gtid;
107     private TransactionImpl tran;
108     /*
109         Logger to log transaction messages
110     */

111     
112     static Logger JavaDoc _logger = LogDomains.getLogger(LogDomains.TRANSACTION_LOGGER);
113
114     public static boolean debug = false;
115     // private static TransactionManagerImpl tm = TransactionManagerImpl.getTransactionManagerImpl();
116

117     public TransactionState(GlobalTID gtid, TransactionImpl tran) {
118         resourceStates = new HashMap();
119         resourceList = new HashMap();
120         seenXids = new HashSet();
121         factories = new ArrayList();
122         this.gtid = gtid;
123         this.tran = tran;
124     }
125
126
127     /**
128      * this is called via callback of Synchronization
129      * right before a transaction commit or rollback
130      * to ensure that all XAResources are properly delisted
131      */

132     synchronized public void beforeCompletion() {
133
134         boolean exceptionThrown = false;
135         XAResource res = null;
136         Iterator e = resourceStates.keySet().iterator();
137         while (e.hasNext()) {
138             try {
139                 res = (XAResource) e.next();
140                 int XAState = getXAState(res);
141                 switch (XAState) {
142                     case NOT_ASSOCIATED:
143                     case FAILED:
144                         break;
145                     case ASSOCIATION_SUSPENDED:
146                     case ASSOCIATED:
147                         Xid xid = (Xid) resourceList.get(res);
148                         res.end(xid, XAResource.TMSUCCESS);
149                         setXAState(res, NOT_ASSOCIATED_INTEGER);
150                         break;
151                     case ROLLING_BACK:
152                     case NOT_EXIST:
153                     default:
154                         throw new IllegalStateException JavaDoc("Wrong XA State: " + XAState/*#Frozen*/);
155                 }
156             } catch (Exception JavaDoc ex) {
157                 setXAState(res, FAILED);
158                 _logger.log(Level.WARNING,"jts.delist_exception",ex);
159                 exceptionThrown = true;
160             }
161         }
162         if (exceptionThrown) {
163             try {
164                 tran.setRollbackOnly();
165             } catch (Exception JavaDoc ex) {}
166         }
167     }
168
169     /**
170      * This is called from OTS to rollback a particular XAResource
171      */

172     synchronized public void rollback(XAResource res)
173         throws IllegalStateException JavaDoc, XAException {
174
175         Xid xid = (Xid) resourceList.get(res);
176         assert_prejdk14(xid != null);
177         int XAState = getXAState(res);
178         switch (XAState) {
179         case NOT_ASSOCIATED:
180         case FAILED:
181             res.rollback(xid);
182             break;
183         case ASSOCIATION_SUSPENDED:
184             res.end(xid, XAResource.TMSUCCESS);
185             setXAState(res, NOT_ASSOCIATED_INTEGER);
186             res.rollback(xid);
187             break;
188         case ASSOCIATED:
189             res.end(xid, XAResource.TMSUCCESS);
190             setXAState(res, NOT_ASSOCIATED_INTEGER);
191             res.rollback(xid);
192             /**
193             // rollback is deferred until delistment
194             setXAState(res, ROLLING_BACK);
195             activeResources++;
196             **/

197             break;
198         case ROLLING_BACK:
199         case NOT_EXIST:
200         default:
201             throw new IllegalStateException JavaDoc("Wrong XAState: " +
202                                             XAState/*#Frozen*/);
203         }
204     }
205
206     private Xid computeXid(XAResource res, Control control)
207         throws Inactive, Unavailable, XAException {
208
209         // one branch id per RM
210
int size = factories.size();
211         for (int i=0; i<size; i++) {
212             XAResource fac = (XAResource) factories.get(i);
213             if (res.isSameRM(fac)) {
214                 // use same branch
215
Xid xid = (Xid) resourceList.get(fac);
216                 return xid;
217             }
218         }
219
220         // use a different branch
221
// XXX ideally should call JTS layer to get the branch id
222
XID xid;
223
224         if( Configuration.isLocalFactory()) {
225             xid = Utility.getXID(((ControlImpl) control).get_localCoordinator());
226         } else {
227             xid = Utility.getXID(control.get_coordinator());
228         }
229         factories.add(res);
230
231         byte [] branchid = parseSize(size);
232         byte [] sname = Configuration.getServerNameByteArray();
233         byte [] branch = new byte[sname.length+1+branchid.length];
234
235         System.arraycopy(sname, 0, branch, 0, sname.length);
236         branch[sname.length] = (byte) ',';
237         System.arraycopy(branchid, 0, branch, sname.length+1, branchid.length);
238
239         xid.setBranchQualifier(branch);
240
241         return xid;
242     }
243
244
245     synchronized public void startAssociation(XAResource res, Control control,
246                                               int status)
247         throws XAException, SystemException JavaDoc, IllegalStateException JavaDoc,
248         RollbackException JavaDoc
249     {
250         OTSResource ref;
251
252         try {
253             // XXX should avoid using XID in JTA layer
254
Xid xid = null;
255             boolean newResource = false;
256             boolean seenXid = false;
257             if (resourceList.get(res) == null) {
258                 // throw RollbackException if try to register
259
// a new resource when a transaction is marked rollback
260
if (status !=
261                     javax.transaction.Status.STATUS_ACTIVE) {
262                     throw new RollbackException JavaDoc();
263                 }
264
265                 newResource = true;
266                 xid = computeXid(res, control);
267                 seenXid = seenXids.contains(xid);
268
269                 // register with OTS
270
if (!seenXid) {
271                     // new branch
272
// COMMENT(Ram J) no need to activate OTSResource object since its local.
273
ref = new OTSResourceImpl(xid, res, this);
274                     if( Configuration.isLocalFactory()) {
275                       ((ControlImpl) control).get_localCoordinator().register_resource(ref);
276                     }
277                     else {
278                       control.get_coordinator().register_resource(ref);
279                     }
280                 }
281                 resourceList.put(res, xid);
282             } else {
283                 // use the previously computed branch id
284
xid = (Xid) resourceList.get(res);
285                 seenXid = seenXids.contains(xid);
286             }
287
288             int XAState = getXAState(res);
289             if (!seenXid) {
290                 // first time this branch is enlisted
291
seenXids.add(xid);
292                 res.start(xid, XAResource.TMNOFLAGS);
293                 setXAState(res, ASSOCIATED_INTEGER);
294             } else {
295                 // have seen this branch before
296
switch (XAState) {
297                 case NOT_ASSOCIATED:
298                 case NOT_EXIST:
299                     res.start(xid, XAResource.TMJOIN);
300                     setXAState(res, ASSOCIATED_INTEGER);
301                     break;
302                 case ASSOCIATION_SUSPENDED:
303                     res.start(xid, XAResource.TMRESUME);
304                     setXAState(res, ASSOCIATED_INTEGER);
305                     break;
306                 case ASSOCIATED:
307                 case FAILED:
308                 case ROLLING_BACK:
309                 default:
310                     throw new IllegalStateException JavaDoc("Wrong XAState: " +
311                                                     XAState/*#Frozen*/);
312                 }
313             }
314
315            /**
316             // need to do connection enlistment for NativeXAResource
317             if (res instanceof NativeXAResource) {
318                 if (newResource) {
319                     ((NativeXAResource) res).enlistConnectionInXA();
320                 }
321             }
322            **/

323         } catch (XAException ex) {
324             setXAState(res, FAILED_INTEGER);
325             throw ex;
326         } catch (Inactive ex) {
327             _logger.log(Level.WARNING,"jts.transaction_inactive",ex);
328             throw new SystemException JavaDoc();
329         } catch (Unavailable ex) {
330             _logger.log(Level.WARNING,"jts.object_unavailable",ex);
331             throw new SystemException JavaDoc();
332         }
333     }
334
335     synchronized
336     public void endAssociation(XAResource xares, int flags)
337         throws XAException, IllegalStateException JavaDoc
338     {
339         try {
340             Xid xid = (Xid) resourceList.get(xares);
341             assert_prejdk14(xid != null);
342             int XAState = getXAState(xares);
343             switch (XAState) {
344             case ASSOCIATED:
345                 if ((flags & XAResource.TMSUCCESS) != 0) {
346                     xares.end(xid, XAResource.TMSUCCESS);
347                     setXAState(xares, NOT_ASSOCIATED_INTEGER);
348                 } else if ((flags & XAResource.TMSUSPEND) != 0) {
349                     xares.end(xid, XAResource.TMSUSPEND);
350                     setXAState(xares, ASSOCIATION_SUSPENDED_INTEGER);
351                 } else {
352                     xares.end(xid, XAResource.TMFAIL);
353                     setXAState(xares, FAILED_INTEGER);
354                 }
355                 break;
356             case ROLLING_BACK:
357                 // rollback deferred XAResources
358
// activeResources--;
359
// cleanupTransactionStateMapping();
360
xares.end(xid, XAResource.TMSUCCESS);
361                 setXAState(xares, NOT_ASSOCIATED_INTEGER);
362                 xares.rollback(xid);
363                 
364                 break;
365             case ASSOCIATION_SUSPENDED:
366                 if ((flags & XAResource.TMSUCCESS) != 0) {
367                     xares.end(xid, XAResource.TMSUCCESS);
368                     setXAState(xares, NOT_ASSOCIATED_INTEGER);
369                 } else if ((flags & XAResource.TMSUSPEND) != 0) {
370                     throw new IllegalStateException JavaDoc
371                         ("Wrong XAState: " + XAState/*#Frozen*/);
372                 } else {
373                     xares.end(xid, XAResource.TMFAIL);
374                     setXAState(xares, FAILED_INTEGER);
375                 }
376                 break;
377             case NOT_ASSOCIATED:
378             case NOT_EXIST:
379             case FAILED:
380             default:
381                 throw new IllegalStateException JavaDoc("Wrong XAState: " + XAState/*#Frozen*/);
382             }
383         } catch (XAException ex) {
384             setXAState(xares, FAILED_INTEGER);
385             throw ex;
386         }
387     }
388
389    // To be called by SynchronizationImpl, if there are any exception
390
// in beforeCompletion() call backs
391
void setRollbackOnly()
392         throws IllegalStateException JavaDoc, SystemException JavaDoc {
393        tran.setRollbackOnly();
394    }
395
396    /**
397     synchronized void cleanupTransactionStateMapping() {
398         if (activeResources == 0) {
399             TransactionManagerImpl tm =
400                 TransactionManagerImpl.getTransactionManagerImpl();
401         }
402     }
403   **/

404
405     synchronized
406     public void registerSynchronization(Synchronization JavaDoc sync,
407                                         Control control,
408                                         boolean interposed)
409         throws RollbackException JavaDoc, IllegalStateException JavaDoc,
410         SystemException JavaDoc {
411
412         try {
413             // One OTS Synchronization object per transaction
414
if (syncImpl == null) {
415                 // syncImpl = new SynchronizationImpl();
416
syncImpl = new SynchronizationImpl(this);
417
418                 // COMMENT(Ram J) syncImpl is a local object. No need to
419
// activate it.
420
if (Configuration.isLocalFactory()) {
421                   ((ControlImpl) control).get_localCoordinator().register_synchronization(syncImpl);
422                 } else {
423                   control.get_coordinator().register_synchronization(syncImpl);
424                 }
425             }
426             syncImpl.addSynchronization(sync, interposed);
427         } catch (TRANSACTION_ROLLEDBACK JavaDoc ex) {
428             throw new RollbackException JavaDoc();
429         } catch (Unavailable ex) {
430             throw new SystemException JavaDoc();
431         } catch (Inactive ex) {
432             throw new IllegalStateException JavaDoc();
433         } catch (Exception JavaDoc ex) {
434             throw new SystemException JavaDoc();
435         }
436     }
437
438     private void setXAState(XAResource res, Integer JavaDoc state) {
439         if (debug) {
440             int oldValue = getXAState(res);
441             _logger.log(Level.FINE,"transaction id : " + gtid);
442             _logger.log(Level.FINE,"res: " + res + "," + oldValue + "," + state);
443         }
444         resourceStates.put(res, state);
445     }
446
447     private int getXAState(XAResource res) {
448         Integer JavaDoc result = (Integer JavaDoc) resourceStates.get(res);
449         if (result == null) return NOT_EXIST;
450         return result.intValue();
451     }
452
453     /**
454      * list all the XAResources that have been enlisted in this
455      * transaction.
456      */

457     public Enumeration listXAResources() {
458         return Collections.enumeration(resourceList.keySet());
459         // return resourceList.keys();
460
}
461
462     /**
463      * return true if res has been enlisted in this transaction;
464      * false otherwise.
465      */

466     public boolean containsXAResource(XAResource res) {
467         return resourceList.containsKey(res);
468     }
469
470     static private void assert_prejdk14(boolean value) {
471         if (!value) {
472             Exception JavaDoc e = new Exception JavaDoc();
473             _logger.log(Level.WARNING,"jts.assert",e);
474         }
475     }
476
477     private static byte[] parseSize(int size) {
478
479           switch(size) {
480             case 0:
481                return new byte[]{0};
482             case 1:
483                return new byte[]{1};
484             case 2:
485                return new byte[]{2};
486             case 3:
487                return new byte[]{3};
488             case 4:
489                return new byte[]{4};
490             case 5:
491                return new byte[]{5};
492             case 6:
493                return new byte[]{6};
494             case 7:
495                return new byte[]{7};
496             case 8:
497                return new byte[]{8};
498             case 9:
499                return new byte[]{9};
500         }
501         int j = 9;
502         byte [] res = new byte[10];
503         while (size > 0) {
504             res[j--] = (byte) (size % 10);
505             size = size / 10;
506         }
507         int len = 9-j;
508         byte [] result = new byte[len];
509         System.arraycopy(res, j+1, result, 0, len);
510         return result;
511     }
512
513 }
514
Popular Tags