Source Code Cross Referenced for SubCoordinator.java in  » Database-JDBC-Connection-Pool » jotm-2.0.10 » org » objectweb » jotm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » jotm 2.0.10 » org.objectweb.jotm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#) SubCoordinator.java 
0003:         *
0004:         * JOTM: Java Open Transaction Manager 
0005:         *
0006:         *
0007:         * This module was originally developed by 
0008:         *
0009:         *  - Bull S.A. as part of the JOnAS application server code released in 
0010:         *    July 1999 (www.bull.com)
0011:         * 
0012:         * --------------------------------------------------------------------------
0013:         *  The original code and portions created by Bull SA are 
0014:         *  Copyright (c) 1999 BULL SA  
0015:         *  All rights reserved.
0016:         *  
0017:         * Redistribution and use in source and binary forms, with or without 
0018:         * modification, are permitted provided that the following conditions are met:
0019:         *
0020:         * -Redistributions of source code must retain the above copyright notice, this
0021:         * list of conditions and the following disclaimer. 
0022:         *
0023:         * -Redistributions in binary form must reproduce the above copyright notice, 
0024:         * this list of conditions and the following disclaimer in the documentation 
0025:         * and/or other materials provided with the distribution. 
0026:         *
0027:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
0028:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
0029:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
0030:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
0031:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
0032:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
0033:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
0034:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
0035:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
0036:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
0037:         * POSSIBILITY OF SUCH DAMAGE.
0038:         * 
0039:         * --------------------------------------------------------------------------
0040:         * Contributor(s):
0041:         * 01/11/06 Christophe Ney cney@batisseurs.com 
0042:         *          Added ResourceManagerListener mechanism to remove ThreadData
0043:         *          dependency.
0044:         *
0045:         * 02/06/18 Marek Prochazka
0046:         *          In addSynchronization() synchronizations are processed the
0047:         *          same way as resources. We add synchro although transaction is
0048:         *          marked rollback-only to be able to send beforeCompletion
0049:         *
0050:         * --------------------------------------------------------------------------
0051:         * $Id: SubCoordinator.java,v 1.37 2005/05/10 22:50:54 tonyortiz Exp $
0052:         * --------------------------------------------------------------------------
0053:         */
0054:
0055:        package org.objectweb.jotm;
0056:
0057:        import java.rmi.RemoteException;
0058:
0059:        import java.util.List;
0060:        import java.util.Vector;
0061:        import java.nio.ByteBuffer;
0062:        import javax.transaction.*;
0063:        import javax.transaction.xa.XAException;
0064:        import javax.transaction.xa.XAResource; // import javax.transaction.xa.Xid;
0065:        import javax.rmi.PortableRemoteObject;
0066:
0067:        import org.objectweb.howl.log.xa.XACommittingTx;
0068:
0069:        /**
0070:         * Log associated to this transaction coordinator
0071:         */
0072:        class SLog {
0073:
0074:            private Vector loggedResources = new Vector();
0075:
0076:            private Vector loggedXids = new Vector();
0077:
0078:            int decision;
0079:            static final int DECISION_TO_COMMIT = 1;
0080:            static final int DECISION_TO_ROLLBACK = 2;
0081:
0082:            public void addResource(XAResource res, Xid xid) {
0083:                if (TraceTm.jta.isDebugEnabled()) {
0084:                    TraceTm.jta.debug("res= " + res);
0085:                    TraceTm.jta.debug("xid= " + xid);
0086:                }
0087:                loggedResources.addElement(res);
0088:                loggedXids.addElement(xid);
0089:            }
0090:
0091:            /**
0092:             * @return a List of logged Resources
0093:             */
0094:            public List getLoggedResources() {
0095:                if (TraceTm.jta.isDebugEnabled()) {
0096:                    TraceTm.jta.debug("logged resources=" + loggedResources);
0097:                }
0098:                return loggedResources;
0099:            }
0100:
0101:            public List getLoggedXids() {
0102:                return loggedXids;
0103:            }
0104:
0105:            public void flushLog(int decide) {
0106:                if (TraceTm.jta.isDebugEnabled()) {
0107:                    TraceTm.jta.debug("decide=" + decide);
0108:                }
0109:                decision = decide;
0110:
0111:                // XXX serialize log on disk
0112:            }
0113:
0114:            public void forgetLog() {
0115:                if (TraceTm.jta.isDebugEnabled()) {
0116:                    TraceTm.jta.debug("forget log");
0117:                }
0118:                // XXX remove file on disk
0119:            }
0120:        }
0121:
0122:        /**
0123:         * This object is the local coordinator. It may be registered as
0124:         * sub-coordinator in case of distributed transaction, so it must
0125:         * be callable remotely and implement Resource
0126:         */
0127:        public class SubCoordinator extends PortableRemoteObject implements 
0128:                Resource {
0129:
0130:            // ------------------------------------------------------------------
0131:            // Object state
0132:            // ------------------------------------------------------------------
0133:
0134:            /**
0135:             * @serial
0136:             */
0137:            private TransactionImpl tx = null;
0138:
0139:            /**
0140:             * List of Synchronization objects
0141:             * @serial
0142:             */
0143:            private Vector synchroList = new Vector();
0144:
0145:            /**
0146:             * List of XAResource objects
0147:             * @serial
0148:             */
0149:            private Vector resourceList = new Vector();
0150:            private Vector javaxxidList = new Vector();
0151:
0152:            /**
0153:             * Keep a reference on TransactionManager
0154:             * @serial
0155:             */
0156:            private TransactionManager tm;
0157:
0158:            /**
0159:             * @serial
0160:             */
0161:            private Xid xid = null;
0162:
0163:            /**
0164:             * @serial
0165:             */
0166:            private SLog log = null;
0167:
0168:            /**
0169:             * javax.transaction.Status     
0170:             * <dl>
0171:             *    <dt>ACTIVE</dt><dd>transaction started, commit phase not started</dd>
0172:             *    <dt>PREPARING</dt><dd>prepare is being sent to resources</dd>
0173:             *    <dt>PREPARED</dt><dd>prepare is done. Must commit now</dd>
0174:             *    <dt>COMMITTING</dt><dd>commit is being sent to resources</dd>
0175:             *    <dt>COMMITTED</dt><dd>commit was successful</dd>
0176:             *    <dt>ROLLING_BACK</dt><dd>not used</dd>
0177:             *    <dt>MARKED_ROLLBACK</dt><dd>setRollbackOnly has been called</dd>
0178:             *    <dt>ROLLEDBACK</dt>
0179:             *    <dd>transaction has been rolled back (or prepare returned "vote_rollback")</dd>
0180:             *    <dt>UNKNOWN</dt><dd>commit raised heuristics</dd>
0181:             *     <dt>NO_TRANSACTION</dt><dd>cannot get the status value from JTM</dd>
0182:             * </dl>
0183:             * @serial
0184:             */
0185:            private int status = Status.STATUS_ACTIVE;
0186:
0187:            /**
0188:             * @serial
0189:             */
0190:            private boolean beforeCompletionDone = false;
0191:
0192:            // ------------------------------------------------------------------
0193:            // Constructors
0194:            // ------------------------------------------------------------------
0195:
0196:            /**
0197:             * constructor used by TransactionImpl
0198:             */
0199:
0200:            SubCoordinator(TransactionImpl tx, Xid xid) throws RemoteException {
0201:
0202:                if (TraceTm.jta.isDebugEnabled()) {
0203:                    TraceTm.jta.debug("tx=" + tx + ",  xid=" + xid);
0204:                }
0205:
0206:                this .tx = tx;
0207:                this .xid = xid;
0208:                this .tm = Current.getTransactionManager();
0209:
0210:                // increment counter for management
0211:                Current.getCurrent().incrementBeginCounter();
0212:                beforeCompletionDone = false;
0213:            }
0214:
0215:            // ------------------------------------------------------------------
0216:            // Resource interface
0217:            // ------------------------------------------------------------------
0218:
0219:            /** 
0220:             * phase 1 of the 2PC.
0221:             *
0222:             * @return int vote commit, rollback, or readonly.
0223:             */
0224:
0225:            public int prepare() throws RemoteException {
0226:
0227:                if (TraceTm.jta.isDebugEnabled()) {
0228:                    TraceTm.jta.debug("status="
0229:                            + StatusHelper.getStatusName(status));
0230:                }
0231:
0232:                try {
0233:                    tx.doDetach(XAResource.TMSUCCESS);
0234:                } catch (SystemException e) {
0235:
0236:                    if (TraceTm.jta.isDebugEnabled()) {
0237:                        String error = "Error when detaching XAResource:" + e
0238:                                + "--" + e.getMessage();
0239:                        TraceTm.jta.debug(error);
0240:                    }
0241:                }
0242:
0243:                switch (status) {
0244:                case Status.STATUS_MARKED_ROLLBACK:
0245:                    doBeforeCompletion(false);
0246:                    doRollback();
0247:                    return Resource.VOTE_ROLLBACK;
0248:                case Status.STATUS_COMMITTED:
0249:                    return Resource.VOTE_COMMIT;
0250:                default:
0251:                    doBeforeCompletion(true);
0252:                    break;
0253:                }
0254:
0255:                // Recheck Status after doBeforeCompletion
0256:
0257:                if (status == Status.STATUS_MARKED_ROLLBACK) {
0258:                    TraceTm.jotm
0259:                            .info("Rollback during beforeCompletion in SubCoordinator.prepare");
0260:                    doRollback();
0261:                    return Resource.VOTE_ROLLBACK;
0262:                }
0263:
0264:                int ret = doPrepare();
0265:
0266:                if (ret == Resource.VOTE_READONLY) {
0267:                    // Transaction completed for this Resource
0268:                    doAfterCompletion();
0269:                }
0270:
0271:                if (TraceTm.jta.isDebugEnabled()) {
0272:                    TraceTm.jta.debug("vote = " + ret);
0273:                }
0274:
0275:                return ret;
0276:            }
0277:
0278:            /** 
0279:             * rollback transaction
0280:             */
0281:
0282:            public void rollback() throws RemoteException {
0283:
0284:                if (TraceTm.jta.isDebugEnabled()) {
0285:                    TraceTm.jta.debug("status="
0286:                            + StatusHelper.getStatusName(status));
0287:                }
0288:
0289:                try {
0290:                    tx.doDetach(XAResource.TMSUCCESS);
0291:                } catch (SystemException e) {
0292:                    if (TraceTm.jta.isDebugEnabled()) {
0293:                        String error = "Error when detaching XAResource:" + e
0294:                                + "--" + e.getMessage();
0295:                        TraceTm.jta.debug(error);
0296:                    }
0297:                }
0298:
0299:                switch (status) {
0300:                case Status.STATUS_ACTIVE:
0301:                case Status.STATUS_MARKED_ROLLBACK:
0302:                case Status.STATUS_ROLLING_BACK:
0303:                    if (TraceTm.jotm.isDebugEnabled()) {
0304:                        TraceTm.jotm.debug("transaction rolling back");
0305:                    }
0306:                    break;
0307:                case Status.STATUS_PREPARED:
0308:                    if (TraceTm.jotm.isDebugEnabled()) {
0309:                        TraceTm.jotm
0310:                                .debug("should not rollback a prepared transaction");
0311:                    }
0312:                    break;
0313:                case Status.STATUS_ROLLEDBACK:
0314:                    if (TraceTm.jotm.isDebugEnabled()) {
0315:                        TraceTm.jotm.debug("already rolledback");
0316:                    }
0317:                    return;
0318:                default:
0319:                    TraceTm.jotm.error("rollback: bad status: "
0320:                            + StatusHelper.getStatusName(status));
0321:                    return;
0322:                }
0323:
0324:                doBeforeCompletion(false);
0325:                doRollback();
0326:            }
0327:
0328:            /** 
0329:             * phase 2 of the 2PC.
0330:             */
0331:
0332:            public void commit() throws RemoteException {
0333:
0334:                if (TraceTm.jta.isDebugEnabled()) {
0335:                    TraceTm.jta.debug("status="
0336:                            + StatusHelper.getStatusName(status));
0337:                }
0338:
0339:                switch (status) {
0340:                case Status.STATUS_PREPARED:
0341:                    break;
0342:                default:
0343:                    TraceTm.jotm.error("commit: bad status: "
0344:                            + StatusHelper.getStatusName(status));
0345:                    return;
0346:                }
0347:
0348:                doCommit();
0349:            }
0350:
0351:            /** 
0352:             * commit 1 phase. Called either from JTM (distributed transaction) or
0353:             * from Transaction.commit (local transaction).
0354:             */
0355:
0356:            public void commit_one_phase() throws RemoteException {
0357:
0358:                if (TraceTm.jta.isDebugEnabled()) {
0359:                    TraceTm.jta.debug("status="
0360:                            + StatusHelper.getStatusName(status));
0361:                }
0362:
0363:                switch (status) {
0364:                case Status.STATUS_ROLLEDBACK:
0365:                    try {
0366:                        tx.doDetach(XAResource.TMSUCCESS);
0367:                    } catch (SystemException e) {
0368:
0369:                        if (TraceTm.jta.isDebugEnabled()) {
0370:                            String error = "Error when detaching XAResource:"
0371:                                    + e + "--" + e.getMessage();
0372:                            TraceTm.jta.debug(error);
0373:                        }
0374:                    }
0375:                    throw new TransactionRolledbackException();
0376:                case Status.STATUS_MARKED_ROLLBACK:
0377:                    doBeforeCompletion(false);
0378:                    try {
0379:                        tx.doDetach(XAResource.TMSUCCESS);
0380:                    } catch (SystemException e) {
0381:
0382:                        if (TraceTm.jta.isDebugEnabled()) {
0383:                            String error = "Error when detaching XAResource:"
0384:                                    + e + "--" + e.getMessage();
0385:                            TraceTm.jta.debug(error);
0386:                        }
0387:                    }
0388:                    doRollback();
0389:                    throw new TransactionRolledbackException();
0390:                case Status.STATUS_COMMITTED:
0391:                    try {
0392:                        tx.doDetach(XAResource.TMSUCCESS);
0393:                    } catch (SystemException e) {
0394:
0395:                        if (TraceTm.jta.isDebugEnabled()) {
0396:                            String error = "Error when detaching XAResource:"
0397:                                    + e + "--" + e.getMessage();
0398:                            TraceTm.jta.debug(error);
0399:                        }
0400:                    }
0401:                    return;
0402:                default:
0403:                    doBeforeCompletion(true);
0404:                    try {
0405:                        tx.doDetach(XAResource.TMSUCCESS);
0406:                    } catch (SystemException e) {
0407:
0408:                        if (TraceTm.jta.isDebugEnabled()) {
0409:                            String error = "Error when detaching XAResource:"
0410:                                    + e + "--" + e.getMessage();
0411:                            TraceTm.jta.debug(error);
0412:                        }
0413:                    }
0414:                    break;
0415:                }
0416:
0417:                // status many have changed in doBeforeCompletion
0418:
0419:                if (TraceTm.jta.isDebugEnabled()) {
0420:                    TraceTm.jta.debug("status="
0421:                            + StatusHelper.getStatusName(status));
0422:                }
0423:
0424:                // Recheck Status after doBeforeCompletion
0425:
0426:                if (status == Status.STATUS_MARKED_ROLLBACK) {
0427:                    TraceTm.jotm
0428:                            .info("Rollback during beforeCompletion in SubCoordinator.commit_one_phase");
0429:                    doRollback();
0430:                    throw new TransactionRolledbackException();
0431:                }
0432:
0433:                // only 1 Resource => 1 phase commit
0434:
0435:                if (resourceList.size() == 1) {
0436:                    doOnePhaseCommit();
0437:                    return;
0438:                }
0439:
0440:                // 2 phase commit
0441:
0442:                int vote = doPrepare();
0443:
0444:                switch (vote) {
0445:                case Resource.VOTE_COMMIT:
0446:                    doCommit();
0447:                    break;
0448:                case Resource.VOTE_READONLY:
0449:                    doAfterCompletion();
0450:                    break;
0451:                case Resource.VOTE_ROLLBACK:
0452:                    doRollback();
0453:                    throw new TransactionRolledbackException();
0454:                }
0455:            }
0456:
0457:            /** 
0458:             * forget heuristics about this transaction.
0459:             */
0460:
0461:            public void forget() throws RemoteException {
0462:                if (TraceTm.jta.isDebugEnabled()) {
0463:                    TraceTm.jta.debug("SubCoordinator.forget()");
0464:                }
0465:                doForget();
0466:            }
0467:
0468:            // ------------------------------------------------------------------
0469:            // Other public methods (interface exposed to Transaction object)
0470:            // ------------------------------------------------------------------
0471:
0472:            /**
0473:             * add a Synchronization to the list
0474:             *
0475:             * @param synchro The javax.transaction.Synchronization object for the 
0476:             *    transaction associated with the target object
0477:             *
0478:             * @exception RollbackException Thrown to indicate that
0479:             *    the transaction has been marked for rollback only.
0480:             *
0481:             * @exception IllegalStateException Thrown if the transaction in the 
0482:             *    target object is in prepared state or the transaction is inactive.
0483:             *
0484:             */
0485:
0486:            public void addSynchronization(Synchronization synchro)
0487:                    throws RollbackException, IllegalStateException {
0488:
0489:                if (TraceTm.jta.isDebugEnabled()) {
0490:                    TraceTm.jta.debug("synchro=" + synchro);
0491:                    TraceTm.jta.debug("status="
0492:                            + StatusHelper.getStatusName(status));
0493:                }
0494:
0495:                // check status: should be ACTIVE.
0496:
0497:                boolean markedRollback = false;
0498:
0499:                switch (status) {
0500:                case Status.STATUS_MARKED_ROLLBACK:
0501:                case Status.STATUS_ROLLEDBACK:
0502:                    markedRollback = true;
0503:                    break;
0504:                case Status.STATUS_ACTIVE:
0505:                    break;
0506:                default:
0507:                    String errorMsg = "addSynchronization: bad status = "
0508:                            + StatusHelper.getStatusName(status);
0509:                    TraceTm.jotm.error(errorMsg);
0510:                    throw new IllegalStateException(errorMsg);
0511:                }
0512:
0513:                // Add synchro to the list of local synchros
0514:
0515:                synchroList.addElement(synchro);
0516:
0517:                // If transaction marked rollback only, we add synchro but we throw
0518:                // the correct exception because nobody can presume what will be done in the
0519:                // Synchronization object, so we must send it beforeCompletion and afterCompletion
0520:                // even in case of rollback.
0521:
0522:                if (markedRollback) {
0523:                    if (TraceTm.jta.isDebugEnabled()) {
0524:                        TraceTm.jta
0525:                                .debug("SubCoordinator.addSynchronization: transaction rollback only");
0526:                    }
0527:                    throw new RollbackException();
0528:                }
0529:
0530:            }
0531:
0532:            /**
0533:             * add a XAResource to the list
0534:             *
0535:             * @param xares  XAResource to register
0536:             *
0537:             * @return true if this datasource was already known
0538:             *
0539:             * @exception IllegalStateException Thrown if the transaction in the 
0540:             *    target object is in prepared state or the transaction is inactive.
0541:             */
0542:
0543:            public synchronized boolean addResource(XAResource xares)
0544:                    throws IllegalStateException {
0545:
0546:                if (TraceTm.jta.isDebugEnabled()) {
0547:                    TraceTm.jta.debug("xares=" + xares);
0548:                    TraceTm.jta.debug("status="
0549:                            + StatusHelper.getStatusName(status));
0550:                }
0551:
0552:                // check status: should be ACTIVE.
0553:
0554:                boolean markedRollback = false;
0555:
0556:                switch (status) {
0557:                case Status.STATUS_MARKED_ROLLBACK:
0558:                    markedRollback = true;
0559:                    break;
0560:                case Status.STATUS_ACTIVE:
0561:                    break;
0562:                default:
0563:                    String errorMsg = "SubCoordinator.addResource: bad status= "
0564:                            + StatusHelper.getStatusName(status);
0565:                    TraceTm.jotm.error(errorMsg);
0566:                    throw new IllegalStateException(errorMsg);
0567:                }
0568:
0569:                // Check if this DataSource is already known
0570:                // -> we must register only ONE resource per DataSource.
0571:
0572:                boolean found = false;
0573:
0574:                for (int i = 0; i < resourceList.size(); i++) {
0575:                    XAResource res = (XAResource) resourceList.elementAt(i);
0576:
0577:                    try {
0578:                        if (res.isSameRM(xares)) {
0579:                            found = true;
0580:                            break;
0581:                        }
0582:                    } catch (XAException e) {
0583:                        String error = "Cannot send res.isSameRM:" + e
0584:                                + " (error code = " + e.errorCode + ") --"
0585:                                + e.getMessage();
0586:                        TraceTm.jotm.error("Exception on resource.isSameRM: "
0587:                                + error);
0588:                    }
0589:                }
0590:
0591:                // add this XAResource to the list
0592:
0593:                if (found == false) {
0594:                    if (TraceTm.jta.isDebugEnabled()) {
0595:                        TraceTm.jta.debug("new XAResource added to the list");
0596:                    }
0597:                    resourceList.addElement(xares);
0598:                }
0599:
0600:                // If transaction marked rollback only, we enlist resource but we throw
0601:                // the correct exception. It is important to enlist the Resource because
0602:                // if we don't, the database would be updated although transaction has been
0603:                // rolled back.
0604:
0605:                if (markedRollback) {
0606:                    if (TraceTm.jta.isDebugEnabled()) {
0607:                        TraceTm.jta
0608:                                .debug("SubCoordinator.addResource: transaction set rollback only");
0609:                    }
0610:                }
0611:
0612:                return found;
0613:            }
0614:
0615:            public synchronized void addJavaxXid(
0616:                    javax.transaction.xa.Xid javaxxid) {
0617:
0618:                if (TraceTm.jta.isDebugEnabled()) {
0619:                    TraceTm.jta.debug("addJavaxXid javaxxid=" + javaxxid);
0620:                }
0621:
0622:                // add this javaxxid to the List at the index location of XAResource
0623:
0624:                javaxxidList.addElement(javaxxid);
0625:
0626:                if (TraceTm.jta.isDebugEnabled()) {
0627:                    TraceTm.jta.debug("new JavaxXid added to the list");
0628:                }
0629:
0630:            }
0631:
0632:            /**
0633:             * return the status of this transaction
0634:             */
0635:
0636:            public int getStatus() {
0637:
0638:                if (TraceTm.jta.isDebugEnabled()) {
0639:                    TraceTm.jta.debug("status="
0640:                            + StatusHelper.getStatusName(status));
0641:                }
0642:
0643:                return status;
0644:            }
0645:
0646:            public javax.transaction.xa.Xid getJavaxXid(int xaresindex) {
0647:                javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
0648:                        .elementAt(xaresindex);
0649:                return myjavaxxid;
0650:            }
0651:
0652:            /**
0653:             * set the transaction "rollback only"
0654:             */
0655:
0656:            public void setRollbackOnly() {
0657:
0658:                if (TraceTm.jta.isDebugEnabled()) {
0659:                    TraceTm.jta.debug("status="
0660:                            + StatusHelper.getStatusName(status));
0661:                }
0662:
0663:                switch (status) {
0664:                case Status.STATUS_ACTIVE:
0665:                case Status.STATUS_UNKNOWN:
0666:                case Status.STATUS_PREPARING:
0667:                    status = Status.STATUS_MARKED_ROLLBACK;
0668:                    break;
0669:                case Status.STATUS_MARKED_ROLLBACK:
0670:                case Status.STATUS_ROLLING_BACK:
0671:                    break;
0672:                case Status.STATUS_PREPARED:
0673:                case Status.STATUS_COMMITTED:
0674:                case Status.STATUS_ROLLEDBACK:
0675:                case Status.STATUS_NO_TRANSACTION:
0676:                case Status.STATUS_COMMITTING:
0677:                    TraceTm.jotm
0678:                            .error("Cannot set transaction as rollback only");
0679:                    TraceTm.jotm.error("Bad status="
0680:                            + StatusHelper.getStatusName(status));
0681:                    break;
0682:                }
0683:            }
0684:
0685:            // ------------------------------------------------------------------
0686:            // private methods
0687:            // ------------------------------------------------------------------
0688:
0689:            /**
0690:             * forget Transaction
0691:             */
0692:
0693:            private void doForget() throws RemoteException {
0694:                if (TraceTm.jta.isDebugEnabled()) {
0695:                    TraceTm.jta.debug("SubCoordinator.doForget()");
0696:                }
0697:
0698:                boolean exception = false;
0699:
0700:                for (int i = 0; i < resourceList.size(); i++) {
0701:                    // Tell this Resource to forget the transaction
0702:                    // Remove from the list ?
0703:                    XAResource xar = (XAResource) resourceList.elementAt(i);
0704:
0705:                    javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
0706:                            .elementAt(i);
0707:                    Xid xid = new XidImpl(this .xid, i);
0708:
0709:                    if (TraceTm.jta.isDebugEnabled()) {
0710:                        TraceTm.jta.debug("xid=        " + xid);
0711:                        TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
0712:                        TraceTm.jta.debug("forgotten with resource= " + xar);
0713:                    }
0714:
0715:                    try {
0716:                        xar.forget(myjavaxxid);
0717:                        // xar.forget(xid);
0718:                    } catch (XAException e) {
0719:                        String error = "Cannot send xar.forget:" + e
0720:                                + " (error code = " + e.errorCode + ") --"
0721:                                + e.getMessage();
0722:                        TraceTm.jotm.error("Got XAException from xar.forget: "
0723:                                + error);
0724:                        exception = true;
0725:                    }
0726:                }
0727:
0728:                if (exception) {
0729:                    throw new RemoteException("XAException on forget");
0730:                }
0731:
0732:                unexportObject(this );
0733:            }
0734:
0735:            /**
0736:             * 2PC phase 1 (prepare)
0737:             * Basically, send prepare on each XAResource and
0738:             * collect the results.
0739:             */
0740:
0741:            private synchronized int doPrepare() throws RemoteException {
0742:                if (TraceTm.jta.isDebugEnabled()) {
0743:                    TraceTm.jta.debug("SubCoordinator.doPrepare()");
0744:                }
0745:
0746:                String jotmPrepareRecord = "PREPARE";
0747:
0748:                int ret = VOTE_READONLY;
0749:                int errors = 0;
0750:
0751:                // No resource
0752:
0753:                if (resourceList.size() == 0) {
0754:                    // increment counter for management
0755:                    Current.getCurrent().incrementCommitCounter();
0756:                    status = Status.STATUS_COMMITTED;
0757:                    return ret;
0758:                }
0759:
0760:                // Creates a log for that transaction, where we will add all the
0761:                // resources that replied VOTE_COMMIT to prepare.
0762:                // Do not flush the log on disk before decision to commit.
0763:
0764:                log = new SLog();
0765:
0766:                // Sends prepare to each resource while no error
0767:                // In case of prepare on sub-coord. we may have only 1 resource.
0768:
0769:                status = Status.STATUS_PREPARING;
0770:
0771:                for (int i = 0; i < resourceList.size(); i++) {
0772:                    XAResource res = (XAResource) resourceList.elementAt(i);
0773:                    javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
0774:                            .elementAt(i);
0775:
0776:                    Xid xid = new XidImpl(this .xid, i);
0777:
0778:                    if (errors > 0) {
0779:
0780:                        if (TraceTm.jta.isDebugEnabled()) {
0781:                            TraceTm.jta.debug("xid=        " + xid);
0782:                            TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
0783:                            TraceTm.jta.debug("rolled back with resource= "
0784:                                    + res);
0785:                        }
0786:
0787:                        try {
0788:                            res.rollback(myjavaxxid);
0789:                            // res.rollback(xid);
0790:                        } catch (XAException e) {
0791:                            String error = "Cannot send res.rollback:" + e
0792:                                    + " (error code = " + e.errorCode + ") --"
0793:                                    + e.getMessage();
0794:                            TraceTm.jotm
0795:                                    .error("Got XAException from res.rollback: "
0796:                                            + error);
0797:                            // Nothing to do ?
0798:                        }
0799:                    } else {
0800:                        if (TraceTm.jta.isDebugEnabled()) {
0801:                            TraceTm.jta.debug("xid=        " + xid);
0802:                            TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
0803:                            TraceTm.jta.debug("prepared with resource= " + res);
0804:                        }
0805:
0806:                        try {
0807:                            switch (res.prepare(myjavaxxid)) {
0808:                            // switch (res.prepare(xid)) {
0809:                            case XAResource.XA_OK:
0810:                                log.addResource(res, xid);
0811:                                ret = VOTE_COMMIT;
0812:                                break;
0813:                            case XAResource.XA_RDONLY:
0814:                                break;
0815:                            }
0816:                        } catch (XAException e) {
0817:                            String error = "Cannot send res.prepare:" + e
0818:                                    + " (error code = " + e.errorCode + ") --"
0819:                                    + e.getMessage();
0820:                            TraceTm.jotm
0821:                                    .error("Got XAException from res.prepare: "
0822:                                            + error);
0823:                            ret = VOTE_ROLLBACK;
0824:                            errors++;
0825:                        }
0826:                    }
0827:                }
0828:
0829:                // Update the status, depending on vote result
0830:                // If all resources returned READ_ONLY, we can forget the transaction
0831:
0832:                switch (ret) {
0833:                case VOTE_READONLY:
0834:                    // increment counter for management
0835:                    Current.getCurrent().incrementCommitCounter();
0836:                    status = Status.STATUS_COMMITTED;
0837:                    break;
0838:                case VOTE_COMMIT:
0839:                    status = Status.STATUS_PREPARED;
0840:                    break;
0841:                case VOTE_ROLLBACK:
0842:                    status = Status.STATUS_ROLLING_BACK;
0843:                    break;
0844:                }
0845:
0846:                // return the global vote
0847:                return ret;
0848:            }
0849:
0850:            /**
0851:             * 2PC - phase 2 (commit)
0852:             * See JTM for heuristics management
0853:             */
0854:
0855:            private synchronized int doCommit() throws RemoteException {
0856:                if (TraceTm.jta.isDebugEnabled()) {
0857:                    TraceTm.jta.debug("SubCoordinator.doCommit()");
0858:                }
0859:
0860:                // We build the Recovery Record in doCommit just in case of a system crash
0861:                // Store the Recovery Record using HOWL so it can manage for us.
0862:                //
0863:                // The Recovery Record consists of two record types:
0864:                //     1. XA Transaction recovery record
0865:                //     2. XA Resource recovery record
0866:                //
0867:                // The XA Transaction recovery record format:
0868:                //     recovery record type1 (byte[3]) - 'RR1'
0869:                //     recovery record stored date-time (long) - 8 bytes
0870:                //     length of transaction's xid (int) - 4 bytes
0871:                //     transaction's xid (byte []) - txxid.length bytes
0872:                //     length of transactions store date-time (int) - 4 bytes
0873:                //     transactions created date-time (byte []) - Date.length bytes
0874:                //     count of XA resources assigned to the transaction (int) - 4 bytes
0875:                //
0876:                // The XA Resource recovery record format:
0877:                //     recovery record type2 (byte[3]) = 'RR2'
0878:                //     length of XA resource (int) - 4 bytes
0879:                //     XA resource (byte []) - xares.length bytes
0880:                //     length of XID assigned to XA resource (int) - 4 bytes
0881:                //     XID assigned to XA resource (byte []) - xid.length bytes
0882:                //     XID status-state (int) = 4 bytes
0883:                //
0884:                // The JOTM Done recovery record format:
0885:                //      recovery record type3 (byte[3]) = 'RR3'
0886:                //      JOTM done value (byte[8]) = 'JOTMDONE'
0887:
0888:                // First check that a log is initialized
0889:
0890:                if (log == null) {
0891:                    TraceTm.jotm.error("doCommit: no log");
0892:                    return -1;
0893:                }
0894:
0895:                int errors = 0;
0896:                int commitnb = 0;
0897:                int heuristicnb = 0;
0898:
0899:                List loggedResources = log.getLoggedResources();
0900:                List loggedXids = log.getLoggedXids();
0901:
0902:                XACommittingTx xaCommitTx = null;
0903:                XACommittingTx xaCommitTxRewrite = null;
0904:
0905:                byte[][] recoveryBuffer = new byte[loggedResources.size() + 1][]; // loggedResources + 1 (recoveryRecord1)
0906:
0907:                byte[] recoveryRecord1 = null;
0908:                byte[] recoveryRecord2 = null;
0909:                ByteBuffer rr1 = null;
0910:                ByteBuffer rr2 = null;
0911:
0912:                String rt1 = "RR1";
0913:                String rt2 = "RR2";
0914:                byte[] jotmDone = new byte[11];
0915:                byte[][] jotmDoneRecord = new byte[1][11];
0916:
0917:                if (Current.getDefaultRecovery()) {
0918:                    Xid txxid = tx.getXid();
0919:                    String stxxid = txxid.toString(true);
0920:                    int txxidlength = stxxid.length();
0921:                    String txdate = tx.getTxDate();
0922:                    int txdatelength = txdate.length();
0923:                    long rcdate = System.currentTimeMillis();
0924:
0925:                    recoveryRecord1 = new byte[3 + 8 + 4 + txxidlength + 4
0926:                            + txdatelength + 4];
0927:
0928:                    rr1 = ByteBuffer.wrap(recoveryRecord1);
0929:                    rr1.put(rt1.getBytes());
0930:                    rr1.putLong(rcdate);
0931:                    rr1.putInt(txxidlength);
0932:                    rr1.put(stxxid.getBytes());
0933:                    rr1.putInt(txdatelength);
0934:                    rr1.put(txdate.getBytes());
0935:                    rr1.putInt(loggedResources.size());
0936:
0937:                    recoveryBuffer[0] = rr1.array();
0938:
0939:                    jotmDone = "RR3JOTMDONE".getBytes();
0940:
0941:                    for (int i = 0; i < loggedResources.size(); i++) {
0942:                        XAResource res = (XAResource) loggedResources.get(i);
0943:                        Xid xid = (Xid) loggedXids.get(i);
0944:                        int rmindex = 99; // Store 99, at recovery we will store the correct index
0945:
0946:                        if (TraceTm.recovery.isDebugEnabled()) {
0947:                            TraceTm.recovery.debug("recovery xid= " + xid);
0948:                            TraceTm.recovery.debug("recovery resource= " + res);
0949:                        }
0950:
0951:                        int reslength = res.toString().length();
0952:                        int resnamelength = res.getClass().getName().length();
0953:                        int xidlength = xid.toString(true).length();
0954:
0955:                        recoveryRecord2 = new byte[3 + 4 + 4 + reslength + 4
0956:                                + resnamelength + 4 + xidlength + 4];
0957:
0958:                        // ByteBuffer rr2 = ByteBuffer.wrap(recoveryRecord2);
0959:                        rr2 = ByteBuffer.wrap(recoveryRecord2);
0960:                        rr2.put(rt2.getBytes());
0961:                        rr2.putInt(rmindex);
0962:                        rr2.putInt(reslength);
0963:                        rr2.put(res.toString().getBytes());
0964:                        rr2.putInt(resnamelength);
0965:                        rr2.put(res.getClass().getName().getBytes());
0966:                        rr2.putInt(xidlength);
0967:                        rr2.put(xid.toString(true).getBytes());
0968:                        rr2.putInt(status);
0969:
0970:                        if (TraceTm.recovery.isDebugEnabled()) {
0971:                            TraceTm.recovery
0972:                                    .debug("Prepare Init RR2 to Recovery Buffer");
0973:                        }
0974:                        recoveryBuffer[i + 1] = rr2.array(); // First record (0) is always rr1
0975:                    }
0976:
0977:                    try {
0978:                        xaCommitTx = TransactionRecoveryImpl
0979:                                .getTransactionRecovery().howlCommitLog(
0980:                                        recoveryBuffer);
0981:                    } catch (Exception e) {
0982:                        // If we cannot write the Log, we cannot perform recovery, rollback transaction
0983:                        status = Status.STATUS_ROLLEDBACK;
0984:
0985:                        String howlerror = "Cannot howlCommitLog:" + e + " --"
0986:                                + e.getMessage();
0987:                        TraceTm.jotm
0988:                                .error("Got LogException from howlCommitLog: "
0989:                                        + howlerror);
0990:                        xaCommitTx = null;
0991:                        doAfterCompletion();
0992:                        log.forgetLog();
0993:
0994:                        throw new TransactionRolledbackException();
0995:                    }
0996:                }
0997:
0998:                // Status Transaction = committing
0999:
1000:                status = Status.STATUS_COMMITTING;
1001:
1002:                // Send commit to each resource prepared
1003:
1004:                for (int i = 0; i < loggedResources.size(); i++) {
1005:                    XAResource res = (XAResource) loggedResources.get(i);
1006:
1007:                    javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
1008:                            .elementAt(i);
1009:                    Xid xid = (Xid) loggedXids.get(i);
1010:
1011:                    // Commit every resource that have been logged even if any of
1012:                    // the commit resources fail. During recovery, the administrator
1013:                    // will resolve any incomplete transactions.
1014:
1015:                    if (TraceTm.jta.isDebugEnabled()) {
1016:                        TraceTm.jta.debug("xid=        " + xid);
1017:                        TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
1018:                        TraceTm.jta.debug("attempting commit with resource= "
1019:                                + res);
1020:                    }
1021:
1022:                    if (Current.getDefaultRecovery()) {
1023:                        int rmindex = 99; // Store 99, at recovery we will store the correct index
1024:                        int reslength = res.toString().length();
1025:                        int resnamelength = res.getClass().getName().length();
1026:                        int xidlength = xid.toString(true).length();
1027:
1028:                        recoveryRecord2 = new byte[3 + 4 + 4 + reslength + 4
1029:                                + resnamelength + 4 + xidlength + 4];
1030:
1031:                        rr2 = ByteBuffer.wrap(recoveryRecord2);
1032:
1033:                        rr2.put(rt2.getBytes());
1034:                        rr2.putInt(rmindex);
1035:                        rr2.putInt(reslength);
1036:                        rr2.put(res.toString().getBytes());
1037:                        rr2.putInt(resnamelength);
1038:                        rr2.put(res.getClass().getName().getBytes());
1039:                        rr2.putInt(xidlength);
1040:                        rr2.put(xid.toString(true).getBytes());
1041:                    }
1042:
1043:                    // commit resource
1044:
1045:                    try {
1046:                        res.commit(myjavaxxid, false);
1047:                        // res.commit(xid, false);
1048:
1049:                        if (Current.getDefaultRecovery()) {
1050:                            rr2.putInt(Status.STATUS_COMMITTED);
1051:                        }
1052:
1053:                        commitnb++; // an XAresource was committed
1054:                    } catch (XAException e) {
1055:                        switch (e.errorCode) {
1056:                        case XAException.XA_HEURHAZ:
1057:                        case XAException.XA_HEURCOM:
1058:                        case XAException.XA_HEURRB:
1059:                        case XAException.XA_HEURMIX:
1060:                            if (TraceTm.jta.isDebugEnabled()) {
1061:                                TraceTm.jta.debug("Heuristic condition= "
1062:                                        + e.getMessage());
1063:                            }
1064:
1065:                            if (Current.getDefaultRecovery()) {
1066:                                rr2.putInt(Status.STATUS_UNKNOWN);
1067:                            }
1068:                            // break;
1069:                        case XAException.XAER_RMERR:
1070:                        case XAException.XAER_NOTA:
1071:                        case XAException.XAER_INVAL:
1072:                        case XAException.XAER_PROTO:
1073:                        case XAException.XAER_RMFAIL:
1074:                            if (TraceTm.jta.isDebugEnabled()) {
1075:                                TraceTm.jta
1076:                                        .debug("RM error= " + e.getMessage());
1077:                            }
1078:
1079:                            if (Current.getDefaultRecovery()) {
1080:                                rr2.putInt(Status.STATUS_COMMITTING);
1081:                            }
1082:                            // break;
1083:                        default:
1084:                            if (TraceTm.jta.isDebugEnabled()) {
1085:                                TraceTm.jta.debug("Default error= "
1086:                                        + e.getMessage());
1087:                            }
1088:
1089:                            if (Current.getDefaultRecovery()) {
1090:                                rr2.putInt(Status.STATUS_ROLLEDBACK);
1091:                            }
1092:                        }
1093:
1094:                        String error = "Cannot send res.commit:" + e
1095:                                + " (error code = " + e.errorCode + ") --"
1096:                                + e.getMessage();
1097:                        TraceTm.jotm.error("Got XAException from res.commit: "
1098:                                + error);
1099:
1100:                        errors++;
1101:                        if (commitnb > 0)
1102:                            heuristicnb++;
1103:                    }
1104:
1105:                    if (Current.getDefaultRecovery()) {
1106:                        if (TraceTm.recovery.isDebugEnabled()) {
1107:                            TraceTm.recovery
1108:                                    .debug("Prepare New RR2 to Recovery Buffer");
1109:                        }
1110:                        recoveryBuffer[i + 1] = rr2.array(); // First record (0) is always rr1
1111:                    }
1112:                }
1113:
1114:                if (errors == 0) {
1115:                    // increment counter for management
1116:                    Current.getCurrent().incrementCommitCounter();
1117:                    // Everything's fine.
1118:                    status = Status.STATUS_COMMITTED;
1119:
1120:                    if (Current.getDefaultRecovery()) {
1121:                        try {
1122:                            if (TraceTm.recovery.isDebugEnabled()) {
1123:                                TraceTm.recovery
1124:                                        .debug("Done howl log, all okay");
1125:                            }
1126:
1127:                            jotmDoneRecord[0] = jotmDone;
1128:                            TransactionRecoveryImpl.getTransactionRecovery()
1129:                                    .howlDoneLog(jotmDoneRecord, xaCommitTx);
1130:                        } catch (Exception f) {
1131:                            String howlerror = "Cannot howlDoneLog:" + f + "--"
1132:                                    + f.getMessage();
1133:                            TraceTm.jotm
1134:                                    .error("Got LogException from howlDoneLog: "
1135:                                            + howlerror);
1136:                        }
1137:                    }
1138:
1139:                    doAfterCompletion();
1140:                    log.forgetLog();
1141:
1142:                    return 0;
1143:                }
1144:
1145:                if (heuristicnb == 0) { // commits on all XAResources failed, just rollback
1146:                    // Transaction has been eventually rolled back
1147:                    status = Status.STATUS_ROLLEDBACK;
1148:
1149:                    if (Current.getDefaultRecovery()) {
1150:                        try {
1151:                            jotmDoneRecord[0] = jotmDone;
1152:                            TransactionRecoveryImpl.getTransactionRecovery()
1153:                                    .howlDoneLog(jotmDoneRecord, xaCommitTx);
1154:                        } catch (Exception f) {
1155:                            String howlerror = "Cannot howlDoneLog" + f + "--"
1156:                                    + f.getMessage();
1157:                            TraceTm.jotm
1158:                                    .error("Got LogException from howlDoneLog: "
1159:                                            + howlerror);
1160:                        }
1161:                    }
1162:
1163:                    doAfterCompletion();
1164:                    log.forgetLog();
1165:
1166:                    throw new TransactionRolledbackException();
1167:                }
1168:
1169:                // Log heuristics if errors
1170:
1171:                if (heuristicnb != 0) { // some XAResource commits succeeded, others failed, heuristicmixed
1172:
1173:                    if (Current.getDefaultRecovery()) {
1174:                        try {
1175:                            if (TraceTm.recovery.isDebugEnabled()) {
1176:                                TraceTm.recovery.debug("Rewrite HowlCommitLog");
1177:                            }
1178:                            xaCommitTxRewrite = TransactionRecoveryImpl
1179:                                    .getTransactionRecovery().howlCommitLog(
1180:                                            recoveryBuffer);
1181:                        } catch (Exception e) {
1182:                            // If we cannot write the Log, we cannot perform recovery, rollback transaction
1183:                            status = Status.STATUS_UNKNOWN;
1184:
1185:                            String howlerror = "Cannot howlCommitLog:" + e
1186:                                    + " --" + e.getMessage();
1187:                            TraceTm.jotm
1188:                                    .error("Got LogException from howlCommitLog: "
1189:                                            + howlerror);
1190:                            xaCommitTx = null;
1191:
1192:                            doAfterCompletion();
1193:                            log.forgetLog();
1194:
1195:                            throw new TransactionRolledbackException();
1196:                        }
1197:
1198:                        // Transaction state is unknown, now job for administrator
1199:                        status = Status.STATUS_UNKNOWN;
1200:
1201:                        try {
1202:                            jotmDoneRecord[0] = jotmDone;
1203:                            TransactionRecoveryImpl.getTransactionRecovery()
1204:                                    .howlDoneLog(jotmDoneRecord, xaCommitTx);
1205:                        } catch (Exception f) {
1206:                            String howlerror = "Cannot howlDoneLog" + f + "--"
1207:                                    + f.getMessage();
1208:                            TraceTm.jotm
1209:                                    .error("Got LogException from howlDoneLog: "
1210:                                            + howlerror);
1211:                        }
1212:                    }
1213:                }
1214:
1215:                status = Status.STATUS_UNKNOWN;
1216:
1217:                doAfterCompletion();
1218:                return -1;
1219:            }
1220:
1221:            /**
1222:             * 1PC (commit one phase)
1223:             */
1224:
1225:            private synchronized void doOnePhaseCommit() throws RemoteException {
1226:                if (TraceTm.jta.isDebugEnabled()) {
1227:                    TraceTm.jta.debug("SubCoordinator.doOnePhaseCommit()");
1228:                }
1229:
1230:                // Only 1 resource: commit with onePhase=true
1231:
1232:                status = Status.STATUS_COMMITTING;
1233:
1234:                XAResource res = (XAResource) resourceList.elementAt(0);
1235:                javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
1236:                        .elementAt(0);
1237:                Xid xid = new XidImpl(this .xid, 0);
1238:
1239:                if (TraceTm.jta.isDebugEnabled()) {
1240:                    TraceTm.jta.debug("xid=        " + xid);
1241:                    TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
1242:                    TraceTm.jta.debug("one phase commit with resource= " + res);
1243:                }
1244:
1245:                try {
1246:                    res.commit(myjavaxxid, true);
1247:                    // res.commit(xid, true);
1248:
1249:                    // increment counter for management
1250:                    Current.getCurrent().incrementCommitCounter();
1251:                    status = Status.STATUS_COMMITTED;
1252:                } catch (XAException e) {
1253:                    status = Status.STATUS_UNKNOWN;
1254:                    String error = "Cannot send res.commit:" + e
1255:                            + " (error code = " + e.errorCode + ") --"
1256:                            + e.getMessage();
1257:                    TraceTm.jotm.error("Got XAException from res.commit: "
1258:                            + error);
1259:
1260:                    if (e.errorCode == XAException.XA_RBROLLBACK) {
1261:                        throw new TransactionRolledbackException("XAException:"
1262:                                + error);
1263:                    }
1264:                    throw new RemoteException("XAException:" + error);
1265:                } finally {
1266:                    doAfterCompletion();
1267:                }
1268:            }
1269:
1270:            /**
1271:             * Rollback every resource involved
1272:             */
1273:
1274:            private synchronized void doRollback() throws RemoteException {
1275:                if (TraceTm.jta.isDebugEnabled()) {
1276:                    TraceTm.jta.debug("SubCoordinator.doRollback()");
1277:                }
1278:
1279:                status = Status.STATUS_ROLLEDBACK;
1280:                boolean heurroll = false;
1281:                String rberror = null;
1282:                int errors = 0;
1283:
1284:                // roll back each resource
1285:                for (int i = 0; i < resourceList.size(); i++) {
1286:
1287:                    XAResource res = (XAResource) resourceList.elementAt(i);
1288:                    javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) javaxxidList
1289:                            .elementAt(i);
1290:                    Xid xid = new XidImpl(this .xid, i);
1291:
1292:                    if (TraceTm.jta.isDebugEnabled()) {
1293:                        TraceTm.jta.debug("xid=        " + xid);
1294:                        TraceTm.jta.debug("myjavaxxid= " + myjavaxxid);
1295:                        TraceTm.jta.debug("rolled back with resource= " + res);
1296:                    }
1297:
1298:                    // Rollback every resource that have been logged even if any of
1299:                    // the rollback resources fail. During recovery, the administrator
1300:                    // will resolve any incomplete transactions.
1301:
1302:                    try {
1303:                        res.rollback(myjavaxxid);
1304:                        // res.rollback(xid);
1305:                    } catch (XAException e) {
1306:                        switch (e.errorCode) {
1307:                        case XAException.XA_HEURHAZ:
1308:                        case XAException.XA_HEURCOM:
1309:                        case XAException.XA_HEURRB:
1310:                        case XAException.XA_HEURMIX:
1311:                            if (TraceTm.jta.isDebugEnabled()) {
1312:                                TraceTm.jta.debug("Heuristic condition= "
1313:                                        + e.getMessage());
1314:                            }
1315:                            heurroll = true;
1316:                        case XAException.XAER_RMERR:
1317:                        case XAException.XAER_NOTA:
1318:                        case XAException.XAER_INVAL:
1319:                        case XAException.XAER_PROTO:
1320:                        case XAException.XAER_RMFAIL:
1321:                            if (TraceTm.jta.isDebugEnabled()) {
1322:                                TraceTm.jta
1323:                                        .debug("RM error= " + e.getMessage());
1324:                            }
1325:                        default:
1326:                            if (TraceTm.jta.isDebugEnabled()) {
1327:                                TraceTm.jta.debug("Default error= "
1328:                                        + e.getMessage());
1329:                            }
1330:                        }
1331:
1332:                        rberror = "Cannot send res.rollback:" + e
1333:                                + " (error code = " + e.errorCode + ") --"
1334:                                + e.getMessage();
1335:                        TraceTm.jotm
1336:                                .error("Got XAException from res.rollback: "
1337:                                        + rberror);
1338:
1339:                        errors++;
1340:                    }
1341:                }
1342:
1343:                // raise Heuristic exception if XAResource returned heuristic
1344:
1345:                if (heurroll) {
1346:                    throw new HeuristicRollback();
1347:                }
1348:
1349:                // raise exception if error on a resource
1350:
1351:                if (errors != 0) {
1352:                    throw new RemoteException(
1353:                            "rollback: Unexpected XAException:" + rberror);
1354:                }
1355:
1356:                // increment counter for management
1357:
1358:                Current.getCurrent().incrementRollbackCounter();
1359:
1360:                doAfterCompletion();
1361:
1362:            }
1363:
1364:            /**
1365:             * before completion
1366:             *
1367:             * @param boolean true if completion ok, false if rollback
1368:             */
1369:
1370:            private void doBeforeCompletion(boolean committing) {
1371:                if (TraceTm.jta.isDebugEnabled()) {
1372:                    TraceTm.jta.debug("doBeforeCompletion committing= "
1373:                            + committing);
1374:                }
1375:
1376:                if (beforeCompletionDone)
1377:                    return;
1378:
1379:                // Unset the timer for this transaction, if any
1380:
1381:                tx.unsetTimer();
1382:
1383:                // For each synchro, send beforeCompletion (not if rollback)
1384:
1385:                if (committing && synchroList.size() > 0) {
1386:                    // We must be in the correct transaction context
1387:                    // See JTA spec. page 13 (3.3.2)
1388:                    // because at beforeCompletion, the bean will write its cache
1389:
1390:                    // Check the trivial case where we already have the correct tx context
1391:
1392:                    Transaction mytx = null;
1393:                    boolean suspended = false;
1394:                    boolean resumed = false;
1395:
1396:                    try {
1397:                        mytx = tm.getTransaction();
1398:                    } catch (SystemException e) {
1399:                        if (TraceTm.jta.isDebugEnabled()) {
1400:                            String error = "Cannot get transaction:" + e + "--"
1401:                                    + e.getMessage();
1402:                            TraceTm.jta.debug(error);
1403:                        }
1404:                    }
1405:
1406:                    // Suspend if another tx context
1407:
1408:                    if (mytx != null && mytx.equals(tx) == false) {
1409:                        try {
1410:                            tm.suspend();
1411:                            suspended = true;
1412:                        } catch (SystemException e) {
1413:                            if (TraceTm.jta.isDebugEnabled()) {
1414:                                String error = "Cannot suspend transaction:"
1415:                                        + e + "--" + e.getMessage();
1416:                                TraceTm.jta.debug(error);
1417:                            }
1418:                        }
1419:                    }
1420:
1421:                    // Resume the good tx context
1422:
1423:                    if (mytx == null || suspended) {
1424:                        try {
1425:                            tm.resume(tx);
1426:                            resumed = true;
1427:                        } catch (SystemException e) {
1428:                            if (TraceTm.jta.isDebugEnabled()) {
1429:                                String error = "Cannot resume transaction:" + e
1430:                                        + "--" + e.getMessage();
1431:                                TraceTm.jta.debug(error);
1432:                            }
1433:                        } catch (InvalidTransactionException e) {
1434:                            if (TraceTm.jta.isDebugEnabled()) {
1435:                                String error = "Cannot resume transaction:" + e
1436:                                        + "--" + e.getMessage();
1437:                                TraceTm.jta.debug(error);
1438:                            }
1439:                        } catch (IllegalStateException e) {
1440:                            if (TraceTm.jta.isDebugEnabled()) {
1441:                                String error = "Cannot resume transaction:" + e
1442:                                        + "--" + e.getMessage();
1443:                                TraceTm.jta.debug(error);
1444:                            }
1445:                        }
1446:                    }
1447:
1448:                    // Call the synchronizations
1449:                    // beforeCompletion may set the TX rollbackonly if something goes wrong
1450:
1451:                    if (TraceTm.jta.isDebugEnabled()) {
1452:                        TraceTm.jta.debug("sychronization list size= "
1453:                                + synchroList.size());
1454:                    }
1455:
1456:                    for (int i = 0; i < synchroList.size(); i++) {
1457:                        Synchronization sync = (Synchronization) synchroList
1458:                                .elementAt(i);
1459:
1460:                        if (TraceTm.jta.isDebugEnabled()) {
1461:                            TraceTm.jta.debug("Synchronization sync= " + sync);
1462:                        }
1463:
1464:                        sync.beforeCompletion();
1465:                    }
1466:
1467:                    // reset context as it was before
1468:
1469:                    if (resumed) {
1470:                        try {
1471:                            tm.suspend();
1472:                        } catch (SystemException e) {
1473:                            if (TraceTm.jta.isDebugEnabled()) {
1474:                                String error = "Cannot suspend transaction:"
1475:                                        + e + "--" + e.getMessage();
1476:                                TraceTm.jta.debug(error);
1477:                            }
1478:                        }
1479:                    }
1480:
1481:                    if (suspended) {
1482:                        try {
1483:                            tm.resume(mytx);
1484:                            resumed = true;
1485:                        } catch (SystemException e) {
1486:                            if (TraceTm.jta.isDebugEnabled()) {
1487:                                String error = "Cannot resume transaction:" + e
1488:                                        + "--" + e.getMessage();
1489:                                TraceTm.jta.debug(error);
1490:                            }
1491:                        } catch (InvalidTransactionException e) {
1492:                            if (TraceTm.jta.isDebugEnabled()) {
1493:                                String error = "Cannot resume transaction:" + e
1494:                                        + "--" + e.getMessage();
1495:                                TraceTm.jta.debug(error);
1496:                            }
1497:                        } catch (IllegalStateException e) {
1498:                            if (TraceTm.jta.isDebugEnabled()) {
1499:                                String error = "Cannot resume transaction:" + e
1500:                                        + "--" + e.getMessage();
1501:                                TraceTm.jta.debug(error);
1502:                            }
1503:                        }
1504:                    }
1505:                }
1506:
1507:                beforeCompletionDone = true;
1508:            }
1509:
1510:            /**
1511:             * after completion
1512:             */
1513:
1514:            private void doAfterCompletion() {
1515:                if (TraceTm.jta.isDebugEnabled()) {
1516:                    TraceTm.jta.debug("doAfterCompletion()");
1517:                }
1518:
1519:                // For each synchro, send afterCompletion
1520:                /// CompletedTransactionListener has been replaced by Synchronization
1521:
1522:                if (TraceTm.jta.isDebugEnabled()) {
1523:                    TraceTm.jta.debug("sychronization list size= "
1524:                            + synchroList.size());
1525:                }
1526:
1527:                for (int i = 0; i < synchroList.size(); i++) {
1528:                    Synchronization sync = (Synchronization) synchroList
1529:                            .elementAt(i);
1530:
1531:                    if (TraceTm.jta.isDebugEnabled()) {
1532:                        TraceTm.jta.debug("Synchronization sync= " + sync);
1533:                        TraceTm.jta.debug("sync.afterCompletion status= "
1534:                                + StatusHelper.getStatusName(status));
1535:                    }
1536:
1537:                    sync.afterCompletion(status);
1538:                }
1539:
1540:                // Forget this transaction.
1541:                // LATER: 
1542:                // - Should not forget it in case of heuristics (for recovery)
1543:                // - May be this could be deferred in case of retry from a client: use a timer.
1544:
1545:                Current.getCurrent().forgetTx(tx.getXid());
1546:
1547:                if (TraceTm.jta.isDebugEnabled()) {
1548:                    TraceTm.jta.debug("SubCoordinator unexported [subcoord="
1549:                            + this  + "]");
1550:                }
1551:
1552:                try {
1553:                    unexportObject(this );
1554:                } catch (Exception e) {
1555:                }
1556:            }
1557:
1558:            // ------------------------------------------------------------------
1559:            // new method for TxImpl
1560:            // ------------------------------------------------------------------
1561:
1562:            public int getXaresIndex(XAResource xares) {
1563:
1564:                if (TraceTm.jta.isDebugEnabled()) {
1565:                    TraceTm.jta.debug("getXaresIndex xares= " + xares);
1566:                    TraceTm.jta.debug("resourceList.size= "
1567:                            + resourceList.size());
1568:                }
1569:
1570:                int xaresIndex = -1;
1571:
1572:                // first, search for an XAResource with the same object reference
1573:                if (TraceTm.jta.isDebugEnabled()) {
1574:                    TraceTm.jta.debug("search xares with same obj ref");
1575:                }
1576:
1577:                for (int i = 0; i < resourceList.size(); i++) {
1578:                    XAResource res = (XAResource) resourceList.elementAt(i);
1579:
1580:                    if (TraceTm.jta.isDebugEnabled()) {
1581:                        TraceTm.jta.debug("res= " + res);
1582:                    }
1583:
1584:                    if (res.equals(xares)) {
1585:                        xaresIndex = i;
1586:                        break;
1587:                    }
1588:                }
1589:
1590:                // if not found, search for a xares with the same RM
1591:                if (xaresIndex == -1) {
1592:                    if (TraceTm.jta.isDebugEnabled()) {
1593:                        TraceTm.jta
1594:                                .debug("not found -> search for xares with same RM");
1595:                    }
1596:
1597:                    for (int i = 0; i < resourceList.size(); i++) {
1598:                        XAResource res = (XAResource) resourceList.elementAt(i);
1599:
1600:                        if (TraceTm.jta.isDebugEnabled()) {
1601:                            TraceTm.jta.debug("res= " + res);
1602:                        }
1603:
1604:                        try {
1605:                            if (res.isSameRM(xares)) {
1606:                                xaresIndex = i;
1607:                                break;
1608:                            }
1609:                        } catch (XAException e) {
1610:                            if (TraceTm.jta.isDebugEnabled()) {
1611:                                String error = "res.isSameRm exception:" + e
1612:                                        + "--" + e.getMessage();
1613:                                TraceTm.jta.debug(error);
1614:                            }
1615:                        }
1616:                    }
1617:                }
1618:
1619:                if (TraceTm.jta.isDebugEnabled()) {
1620:                    TraceTm.jta.debug("xaresIndex= " + xaresIndex);
1621:                }
1622:
1623:                return xaresIndex;
1624:            }
1625:
1626:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.