1 54 55 package org.objectweb.jotm; 56 57 import java.rmi.RemoteException ; 58 59 import java.util.List ; 60 import java.util.Vector ; 61 import java.nio.ByteBuffer ; 62 import javax.transaction.*; 63 import javax.transaction.xa.XAException ; 64 import javax.transaction.xa.XAResource ; 65 import javax.rmi.PortableRemoteObject ; 67 68 import org.objectweb.howl.log.xa.XACommittingTx; 69 70 73 class SLog { 74 75 private Vector loggedResources = new Vector (); 76 77 private Vector loggedXids = new Vector (); 78 79 int decision; 80 static final int DECISION_TO_COMMIT = 1; 81 static final int DECISION_TO_ROLLBACK = 2; 82 83 public void addResource( XAResource res, Xid xid ) 84 { 85 if (TraceTm.jta.isDebugEnabled()) { 86 TraceTm.jta.debug("res= "+ res); 87 TraceTm.jta.debug("xid= "+ xid); 88 } 89 loggedResources.addElement(res); 90 loggedXids.addElement(xid); 91 } 92 93 96 public List getLoggedResources() { 97 if (TraceTm.jta.isDebugEnabled()) { 98 TraceTm.jta.debug("logged resources="+ loggedResources); 99 } 100 return loggedResources; 101 } 102 103 public List getLoggedXids() { 104 return loggedXids; 105 } 106 107 public void flushLog(int decide) { 108 if (TraceTm.jta.isDebugEnabled()) { 109 TraceTm.jta.debug("decide="+ decide); 110 } 111 decision = decide; 112 113 } 115 116 public void forgetLog() { 117 if (TraceTm.jta.isDebugEnabled()) { 118 TraceTm.jta.debug("forget log"); 119 } 120 } 122 } 123 124 129 public class SubCoordinator extends PortableRemoteObject implements Resource { 130 131 135 138 private TransactionImpl tx = null; 139 140 144 private Vector synchroList = new Vector (); 145 146 150 private Vector resourceList = new Vector (); 151 private Vector javaxxidList = new Vector (); 152 153 157 private TransactionManager tm; 158 159 162 private Xid xid = null; 163 164 167 private SLog log = null; 168 169 186 private int status = Status.STATUS_ACTIVE; 187 188 191 private boolean beforeCompletionDone = false; 192 193 197 200 201 SubCoordinator(TransactionImpl tx, Xid xid) throws RemoteException { 202 203 if (TraceTm.jta.isDebugEnabled()) { 204 TraceTm.jta.debug("tx="+ tx +", xid="+ xid); 205 } 206 207 this.tx = tx; 208 this.xid = xid; 209 this.tm = Current.getTransactionManager(); 210 211 Current.getCurrent().incrementBeginCounter(); 213 beforeCompletionDone = false; 214 } 215 216 220 225 226 public int prepare() throws RemoteException { 227 228 if (TraceTm.jta.isDebugEnabled()) { 229 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 230 } 231 232 try { 233 tx.doDetach(XAResource.TMSUCCESS); 234 } catch (SystemException e) { 235 236 if (TraceTm.jta.isDebugEnabled()) { 237 String error = 238 "Error when detaching XAResource:" 239 + e 240 + "--" 241 + e.getMessage(); 242 TraceTm.jta.debug(error); 243 } 244 } 245 246 switch (status) { 247 case Status.STATUS_MARKED_ROLLBACK : 248 doBeforeCompletion(false); 249 doRollback(); 250 return Resource.VOTE_ROLLBACK; 251 case Status.STATUS_COMMITTED : 252 return Resource.VOTE_COMMIT; 253 default : 254 doBeforeCompletion(true); 255 break; 256 } 257 258 260 if (status == Status.STATUS_MARKED_ROLLBACK) { 261 TraceTm.jotm.info( 262 "Rollback during beforeCompletion in SubCoordinator.prepare"); 263 doRollback(); 264 return Resource.VOTE_ROLLBACK; 265 } 266 267 int ret = doPrepare(); 268 269 if (ret == Resource.VOTE_READONLY) { 270 doAfterCompletion(); 272 } 273 274 if (TraceTm.jta.isDebugEnabled()) { 275 TraceTm.jta.debug("vote = " + ret); 276 } 277 278 return ret; 279 } 280 281 284 285 public void rollback() throws RemoteException { 286 287 if (TraceTm.jta.isDebugEnabled()) { 288 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 289 } 290 291 try { 292 tx.doDetach(XAResource.TMSUCCESS); 293 } catch (SystemException e) { 294 if (TraceTm.jta.isDebugEnabled()) { 295 String error = 296 "Error when detaching XAResource:" 297 + e 298 + "--" 299 + e.getMessage(); 300 TraceTm.jta.debug(error); 301 } 302 } 303 304 switch (status) { 305 case Status.STATUS_ACTIVE : 306 case Status.STATUS_MARKED_ROLLBACK : 307 case Status.STATUS_ROLLING_BACK: 308 if (TraceTm.jotm.isDebugEnabled()) { 309 TraceTm.jotm.debug("transaction rolling back"); 310 } 311 break; 312 case Status.STATUS_PREPARED: 313 if (TraceTm.jotm.isDebugEnabled()) { 314 TraceTm.jotm.debug("should not rollback a prepared transaction"); 315 } 316 break; 317 case Status.STATUS_ROLLEDBACK : 318 if (TraceTm.jotm.isDebugEnabled()) { 319 TraceTm.jotm.debug("already rolledback"); 320 } 321 return; 322 default : 323 TraceTm.jotm.error( 324 "rollback: bad status: " 325 + StatusHelper.getStatusName(status)); 326 return; 327 } 328 329 doBeforeCompletion(false); 330 doRollback(); 331 } 332 333 336 337 public void commit() throws RemoteException { 338 339 if (TraceTm.jta.isDebugEnabled()) { 340 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 341 } 342 343 switch (status) { 344 case Status.STATUS_PREPARED : 345 break; 346 default : 347 TraceTm.jotm.error( 348 "commit: bad status: " 349 + StatusHelper.getStatusName(status)); 350 return; 351 } 352 353 doCommit(); 354 } 355 356 360 361 public void commit_one_phase() throws RemoteException { 362 363 if (TraceTm.jta.isDebugEnabled()) { 364 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 365 } 366 367 switch (status) { 368 case Status.STATUS_ROLLEDBACK : 369 try { 370 tx.doDetach(XAResource.TMSUCCESS); 371 } catch (SystemException e) { 372 373 if (TraceTm.jta.isDebugEnabled()) { 374 String error = 375 "Error when detaching XAResource:" 376 + e 377 + "--" 378 + e.getMessage(); 379 TraceTm.jta.debug(error); 380 } 381 } 382 throw new TransactionRolledbackException(); 383 case Status.STATUS_MARKED_ROLLBACK : 384 doBeforeCompletion(false); 385 try { 386 tx.doDetach(XAResource.TMSUCCESS); 387 } catch (SystemException e) { 388 389 if (TraceTm.jta.isDebugEnabled()) { 390 String error = 391 "Error when detaching XAResource:" 392 + e 393 + "--" 394 + e.getMessage(); 395 TraceTm.jta.debug(error); 396 } 397 } 398 doRollback(); 399 throw new TransactionRolledbackException(); 400 case Status.STATUS_COMMITTED : 401 try { 402 tx.doDetach(XAResource.TMSUCCESS); 403 } catch (SystemException e) { 404 405 if (TraceTm.jta.isDebugEnabled()) { 406 String error = 407 "Error when detaching XAResource:" 408 + e 409 + "--" 410 + e.getMessage(); 411 TraceTm.jta.debug(error); 412 } 413 } 414 return; 415 default : 416 doBeforeCompletion(true); 417 try { 418 tx.doDetach(XAResource.TMSUCCESS); 419 } catch (SystemException e) { 420 421 if (TraceTm.jta.isDebugEnabled()) { 422 String error = 423 "Error when detaching XAResource:" 424 + e 425 + "--" 426 + e.getMessage(); 427 TraceTm.jta.debug(error); 428 } 429 } 430 break; 431 } 432 433 435 if (TraceTm.jta.isDebugEnabled()) { 436 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 437 } 438 439 441 if (status == Status.STATUS_MARKED_ROLLBACK) { 442 TraceTm.jotm.info( 443 "Rollback during beforeCompletion in SubCoordinator.commit_one_phase"); 444 doRollback(); 445 throw new TransactionRolledbackException(); 446 } 447 448 450 if (resourceList.size() == 1) { 451 doOnePhaseCommit(); 452 return; 453 } 454 455 457 int vote = doPrepare(); 458 459 switch (vote) { 460 case Resource.VOTE_COMMIT : 461 doCommit(); 462 break; 463 case Resource.VOTE_READONLY : 464 doAfterCompletion(); 465 break; 466 case Resource.VOTE_ROLLBACK : 467 doRollback(); 468 throw new TransactionRolledbackException(); 469 } 470 } 471 472 475 476 public void forget() throws RemoteException { 477 if (TraceTm.jta.isDebugEnabled()) { 478 TraceTm.jta.debug("SubCoordinator.forget()"); 479 } 480 doForget(); 481 } 482 483 487 500 501 public void addSynchronization(Synchronization synchro) 502 throws RollbackException, IllegalStateException { 503 504 if (TraceTm.jta.isDebugEnabled()) { 505 TraceTm.jta.debug("synchro="+ synchro); 506 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 507 } 508 509 511 boolean markedRollback = false; 512 513 switch (status) { 514 case Status.STATUS_MARKED_ROLLBACK : 515 case Status.STATUS_ROLLEDBACK : 516 markedRollback = true; 517 break; 518 case Status.STATUS_ACTIVE : 519 break; 520 default : 521 String errorMsg = 522 "addSynchronization: bad status = " 523 + StatusHelper.getStatusName(status); 524 TraceTm.jotm.error(errorMsg); 525 throw new IllegalStateException (errorMsg); 526 } 527 528 530 synchroList.addElement(synchro); 531 532 537 if (markedRollback) { 538 if (TraceTm.jta.isDebugEnabled()) { 539 TraceTm.jta.debug("SubCoordinator.addSynchronization: transaction rollback only"); 540 } 541 throw new RollbackException(); 542 } 543 544 } 545 546 556 557 public synchronized boolean addResource(XAResource xares) 558 throws IllegalStateException { 559 560 if (TraceTm.jta.isDebugEnabled()) { 561 TraceTm.jta.debug("xares="+ xares); 562 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 563 } 564 565 567 boolean markedRollback = false; 568 569 switch (status) { 570 case Status.STATUS_MARKED_ROLLBACK : 571 markedRollback = true; 572 break; 573 case Status.STATUS_ACTIVE : 574 break; 575 default : 576 String errorMsg = 577 "SubCoordinator.addResource: bad status= " 578 + StatusHelper.getStatusName(status); 579 TraceTm.jotm.error(errorMsg); 580 throw new IllegalStateException (errorMsg); 581 } 582 583 586 boolean found = false; 587 588 for (int i = 0; i < resourceList.size(); i++) { 589 XAResource res = (XAResource ) resourceList.elementAt(i); 590 591 try { 592 if (res.isSameRM(xares)) { 593 found = true; 594 break; 595 } 596 } catch (XAException e) { 597 String error = 598 "Cannot send res.isSameRM:" 599 + e 600 + " (error code = " 601 + e.errorCode 602 + ") --" 603 + e.getMessage(); 604 TraceTm.jotm.error( 605 "Exception on resource.isSameRM: "+ error); 606 } 607 } 608 609 611 if (found == false) { 612 if (TraceTm.jta.isDebugEnabled()) { 613 TraceTm.jta.debug("new XAResource added to the list"); 614 } 615 resourceList.addElement(xares); 616 } 617 618 623 if (markedRollback) { 624 if (TraceTm.jta.isDebugEnabled()) { 625 TraceTm.jta.debug("SubCoordinator.addResource: transaction set rollback only"); 626 } 627 } 628 629 return found; 630 } 631 632 public synchronized void addJavaxXid(javax.transaction.xa.Xid javaxxid) { 633 634 if (TraceTm.jta.isDebugEnabled()) { 635 TraceTm.jta.debug("addJavaxXid javaxxid="+ javaxxid); 636 } 637 638 640 javaxxidList.addElement(javaxxid); 641 642 if (TraceTm.jta.isDebugEnabled()) { 643 TraceTm.jta.debug("new JavaxXid added to the list"); 644 } 645 646 } 647 648 651 652 public int getStatus() { 653 654 if (TraceTm.jta.isDebugEnabled()) { 655 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 656 } 657 658 return status; 659 } 660 661 public javax.transaction.xa.Xid getJavaxXid(int xaresindex) { 662 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid ) javaxxidList.elementAt(xaresindex); 663 return myjavaxxid; 664 } 665 666 669 670 public void setRollbackOnly() { 671 672 if (TraceTm.jta.isDebugEnabled()) { 673 TraceTm.jta.debug("status="+ StatusHelper.getStatusName(status)); 674 } 675 676 switch (status) { 677 case Status.STATUS_ACTIVE : 678 case Status.STATUS_UNKNOWN : 679 case Status.STATUS_PREPARING : 680 status = Status.STATUS_MARKED_ROLLBACK; 681 break; 682 case Status.STATUS_MARKED_ROLLBACK : 683 case Status.STATUS_ROLLING_BACK : 684 break; 685 case Status.STATUS_PREPARED : 686 case Status.STATUS_COMMITTED : 687 case Status.STATUS_ROLLEDBACK : 688 case Status.STATUS_NO_TRANSACTION : 689 case Status.STATUS_COMMITTING : 690 TraceTm.jotm.error("Cannot set transaction as rollback only"); 691 TraceTm.jotm.error("Bad status="+ StatusHelper.getStatusName(status)); 692 break; 693 } 694 } 695 696 700 703 704 private void doForget() throws RemoteException { 705 if (TraceTm.jta.isDebugEnabled()) { 706 TraceTm.jta.debug("SubCoordinator.doForget()"); 707 } 708 709 boolean exception = false; 710 711 for (int i = 0; i < resourceList.size(); i++) { 712 XAResource xar = (XAResource ) resourceList.elementAt(i); 715 716 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid )javaxxidList.elementAt(i); 717 Xid xid = new XidImpl( this.xid, i ); 718 719 if (TraceTm.jta.isDebugEnabled()) { 720 TraceTm.jta.debug("xid= " + xid); 721 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 722 TraceTm.jta.debug("forgotten with resource= " + xar); 723 } 724 725 try { 726 xar.forget(myjavaxxid); 727 } catch (XAException e) { 729 String error = 730 "Cannot send xar.forget:" 731 + e 732 + " (error code = " 733 + e.errorCode 734 + ") --" 735 + e.getMessage(); 736 TraceTm.jotm.error( 737 "Got XAException from xar.forget: "+ error); 738 exception = true; 739 } 740 } 741 742 if (exception) { 743 throw new RemoteException ("XAException on forget"); 744 } 745 746 unexportObject(this); 747 } 748 749 754 755 private synchronized int doPrepare() throws RemoteException { 756 if (TraceTm.jta.isDebugEnabled()) { 757 TraceTm.jta.debug("SubCoordinator.doPrepare()"); 758 } 759 760 String jotmPrepareRecord = "PREPARE"; 761 762 int ret = VOTE_READONLY; 763 int errors = 0; 764 765 767 if (resourceList.size() == 0) { 768 Current.getCurrent().incrementCommitCounter(); 770 status = Status.STATUS_COMMITTED; 771 return ret; 772 } 773 774 778 log = new SLog(); 779 780 783 status = Status.STATUS_PREPARING; 784 785 for (int i = 0; i < resourceList.size(); i++) { 786 XAResource res = (XAResource ) resourceList.elementAt(i); 787 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid ) javaxxidList.elementAt(i); 788 789 Xid xid = new XidImpl( this.xid, i ); 790 791 if (errors > 0) { 792 793 if (TraceTm.jta.isDebugEnabled()) { 794 TraceTm.jta.debug("xid= " + xid); 795 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 796 TraceTm.jta.debug("rolled back with resource= " + res); 797 } 798 799 try { 800 res.rollback(myjavaxxid); 801 } catch (XAException e) { 803 String error = 804 "Cannot send res.rollback:" 805 + e 806 + " (error code = " 807 + e.errorCode 808 + ") --" 809 + e.getMessage(); 810 TraceTm.jotm.error( 811 "Got XAException from res.rollback: "+ error); 812 } 814 } else { 815 if (TraceTm.jta.isDebugEnabled()) { 816 TraceTm.jta.debug("xid= " + xid); 817 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 818 TraceTm.jta.debug("prepared with resource= " + res); 819 } 820 821 try { 822 switch (res.prepare(myjavaxxid)) { 823 case XAResource.XA_OK : 825 log.addResource(res,xid); 826 ret = VOTE_COMMIT; 827 break; 828 case XAResource.XA_RDONLY : 829 break; 830 } 831 } catch (XAException e) { 832 String error = 833 "Cannot send res.prepare:" 834 + e 835 + " (error code = " 836 + e.errorCode 837 + ") --" 838 + e.getMessage(); 839 TraceTm.jotm.error( 840 "Got XAException from res.prepare: "+ error); 841 ret = VOTE_ROLLBACK; 842 errors++; 843 } 844 } 845 } 846 847 850 switch (ret) { 851 case VOTE_READONLY : 852 Current.getCurrent().incrementCommitCounter(); 854 status = Status.STATUS_COMMITTED; 855 break; 856 case VOTE_COMMIT : 857 status = Status.STATUS_PREPARED; 858 break; 859 case VOTE_ROLLBACK : 860 status = Status.STATUS_ROLLING_BACK; 861 break; 862 } 863 864 return ret; 866 } 867 868 872 873 private synchronized int doCommit() throws RemoteException { 874 if (TraceTm.jta.isDebugEnabled()) { 875 TraceTm.jta.debug("SubCoordinator.doCommit()"); 876 } 877 878 906 908 if (log == null) { 909 TraceTm.jotm.error("doCommit: no log"); 910 return -1; 911 } 912 913 int errors = 0; 914 int commitnb = 0; 915 int heuristicnb = 0; 916 917 List loggedResources = log.getLoggedResources(); 918 List loggedXids = log.getLoggedXids(); 919 920 XACommittingTx xaCommitTx = null; 921 XACommittingTx xaCommitTxRewrite = null; 922 923 byte [] [] recoveryBuffer = new byte [loggedResources.size() + 1] []; 925 byte [] recoveryRecord1 = null; 926 byte [] recoveryRecord2 = null; 927 ByteBuffer rr1 = null; 928 ByteBuffer rr2 = null; 929 930 String rt1 = "RR1"; 931 String rt2 = "RR2"; 932 byte [] jotmDone = new byte [11]; 933 byte [] [] jotmDoneRecord = new byte [1] [11]; 934 935 if (Current.getDefaultRecovery()) { 936 Xid txxid = tx.getXid(); 937 String stxxid = txxid.toString(true); 938 int txxidlength = stxxid.length(); 939 String txdate = tx.getTxDate(); 940 int txdatelength= txdate.length(); 941 long rcdate = System.currentTimeMillis(); 942 943 recoveryRecord1 = new byte[3+8+4+txxidlength+4+txdatelength+4]; 944 945 rr1 = ByteBuffer.wrap(recoveryRecord1); 946 rr1.put(rt1.getBytes()); 947 rr1.putLong(rcdate); 948 rr1.putInt(txxidlength); 949 rr1.put(stxxid.getBytes()); 950 rr1.putInt(txdatelength); 951 rr1.put(txdate.getBytes()); 952 rr1.putInt(loggedResources.size()); 953 954 recoveryBuffer [0] = rr1.array(); 955 956 jotmDone = "RR3JOTMDONE".getBytes(); 957 958 for (int i = 0; i < loggedResources.size(); i++) { 959 XAResource res = (XAResource ) loggedResources.get(i); 960 Xid xid = (Xid)loggedXids.get(i); 961 int rmindex = 99; 963 if (TraceTm.recovery.isDebugEnabled()) { 964 TraceTm.recovery.debug("recovery xid= " + xid); 965 TraceTm.recovery.debug("recovery resource= " + res); 966 } 967 968 int reslength = res.toString().length(); 969 int resnamelength = res.getClass().getName().length(); 970 int xidlength = xid.toString(true).length(); 971 972 recoveryRecord2 = new byte[3+4+4+reslength+4+resnamelength+4+xidlength+4]; 973 974 rr2 = ByteBuffer.wrap(recoveryRecord2); 976 rr2.put(rt2.getBytes()); 977 rr2.putInt(rmindex); 978 rr2.putInt(reslength); 979 rr2.put(res.toString().getBytes()); 980 rr2.putInt(resnamelength); 981 rr2.put(res.getClass().getName().getBytes()); 982 rr2.putInt(xidlength); 983 rr2.put(xid.toString(true).getBytes()); 984 rr2.putInt(status); 985 986 if (TraceTm.recovery.isDebugEnabled()) { 987 TraceTm.recovery.debug("Prepare Init RR2 to Recovery Buffer"); 988 } 989 recoveryBuffer [i+1] = rr2.array(); } 991 992 try { 993 xaCommitTx = TransactionRecoveryImpl.getTransactionRecovery().howlCommitLog(recoveryBuffer); 994 } catch (Exception e) { 995 status = Status.STATUS_ROLLEDBACK; 997 998 String howlerror = 999 "Cannot howlCommitLog:" 1000 + e 1001 + " --" 1002 + e.getMessage(); 1003 TraceTm.jotm.error("Got LogException from howlCommitLog: "+ howlerror); 1004 xaCommitTx = null; 1005 doAfterCompletion(); 1006 log.forgetLog(); 1007 1008 throw new TransactionRolledbackException(); 1009 } 1010 } 1011 1012 1014 status = Status.STATUS_COMMITTING; 1015 1016 1018 for (int i = 0; i < loggedResources.size(); i++) { 1019 XAResource res = (XAResource ) loggedResources.get(i); 1020 1021 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid ) javaxxidList.elementAt(i); 1022 Xid xid = (Xid) loggedXids.get(i); 1023 1024 1028 if (TraceTm.jta.isDebugEnabled()) { 1029 TraceTm.jta.debug("xid= " + xid); 1030 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 1031 TraceTm.jta.debug("attempting commit with resource= " + res); 1032 } 1033 1034 if (Current.getDefaultRecovery()) { 1035 int rmindex = 99; int reslength = res.toString().length(); 1037 int resnamelength = res.getClass().getName().length(); 1038 int xidlength = xid.toString(true).length(); 1039 1040 recoveryRecord2 = new byte[3+4+4+reslength+4+resnamelength+4+xidlength+4]; 1041 1042 rr2 = ByteBuffer.wrap(recoveryRecord2); 1043 1044 rr2.put(rt2.getBytes()); 1045 rr2.putInt(rmindex); 1046 rr2.putInt(reslength); 1047 rr2.put(res.toString().getBytes()); 1048 rr2.putInt(resnamelength); 1049 rr2.put(res.getClass().getName().getBytes()); 1050 rr2.putInt(xidlength); 1051 rr2.put(xid.toString(true).getBytes()); 1052 } 1053 1054 1056 try { 1057 res.commit(myjavaxxid, false); 1058 1060 if (Current.getDefaultRecovery()) { 1061 rr2.putInt(Status.STATUS_COMMITTED); 1062 } 1063 1064 commitnb++; } catch (XAException e) { 1066 switch (e.errorCode) { 1067 case XAException.XA_HEURHAZ : 1068 case XAException.XA_HEURCOM : 1069 case XAException.XA_HEURRB : 1070 case XAException.XA_HEURMIX : 1071 if (TraceTm.jta.isDebugEnabled()) { 1072 TraceTm.jta.debug("Heuristic condition= " + e.getMessage()); 1073 } 1074 1075 if (Current.getDefaultRecovery()) { 1076 rr2.putInt(Status.STATUS_UNKNOWN); 1077 } 1078 case XAException.XAER_RMERR : 1080 case XAException.XAER_NOTA : 1081 case XAException.XAER_INVAL : 1082 case XAException.XAER_PROTO: 1083 case XAException.XAER_RMFAIL : 1084 if (TraceTm.jta.isDebugEnabled()) { 1085 TraceTm.jta.debug("RM error= " + e.getMessage()); 1086 } 1087 1088 if (Current.getDefaultRecovery()) { 1089 rr2.putInt(Status.STATUS_COMMITTING); 1090 } 1091 default : 1093 if (TraceTm.jta.isDebugEnabled()) { 1094 TraceTm.jta.debug("Default error= " + e.getMessage()); 1095 } 1096 1097 if (Current.getDefaultRecovery()) { 1098 rr2.putInt(Status.STATUS_ROLLEDBACK); 1099 } 1100 } 1101 1102 String error = 1103 "Cannot send res.commit:" 1104 + e 1105 + " (error code = " 1106 + e.errorCode 1107 + ") --" 1108 + e.getMessage(); 1109 TraceTm.jotm.error( 1110 "Got XAException from res.commit: "+ error); 1111 1112 errors++; 1113 if (commitnb > 0) 1114 heuristicnb++; 1115 } 1116 1117 if (Current.getDefaultRecovery()) { 1118 if (TraceTm.recovery.isDebugEnabled()) { 1119 TraceTm.recovery.debug("Prepare New RR2 to Recovery Buffer"); 1120 } 1121 recoveryBuffer [i+1] = rr2.array(); } 1123 } 1124 1125 if (errors == 0) { 1126 Current.getCurrent().incrementCommitCounter(); 1128 status = Status.STATUS_COMMITTED; 1130 1131 1132 if (Current.getDefaultRecovery()) { 1133 try { 1134 if (TraceTm.recovery.isDebugEnabled()) { 1135 TraceTm.recovery.debug("Done howl log, all okay"); 1136 } 1137 1138 jotmDoneRecord [0] = jotmDone; 1139 TransactionRecoveryImpl.getTransactionRecovery().howlDoneLog(jotmDoneRecord, xaCommitTx); 1140 } catch (Exception f) { 1141 String howlerror = 1142 "Cannot howlDoneLog:" 1143 + f 1144 + "--" 1145 + f.getMessage(); 1146 TraceTm.jotm.error("Got LogException from howlDoneLog: "+ howlerror); 1147 } 1148 } 1149 1150 doAfterCompletion(); 1151 log.forgetLog(); 1152 1153 return 0; 1154 } 1155 1156 if (heuristicnb == 0) { status = Status.STATUS_ROLLEDBACK; 1159 1160 if (Current.getDefaultRecovery()) { 1161 try { 1162 jotmDoneRecord [0] = jotmDone; 1163 TransactionRecoveryImpl.getTransactionRecovery().howlDoneLog(jotmDoneRecord, xaCommitTx); 1164 } catch (Exception f) { 1165 String howlerror = 1166 "Cannot howlDoneLog" 1167 + f 1168 + "--" 1169 + f.getMessage(); 1170 TraceTm.jotm.error("Got LogException from howlDoneLog: "+ howlerror); 1171 } 1172 } 1173 1174 doAfterCompletion(); 1175 log.forgetLog(); 1176 1177 throw new TransactionRolledbackException(); 1178 } 1179 1180 1182 if (heuristicnb != 0) { 1184 if (Current.getDefaultRecovery()) { 1185 try { 1186 if (TraceTm.recovery.isDebugEnabled()) { 1187 TraceTm.recovery.debug("Rewrite HowlCommitLog"); 1188 } 1189 xaCommitTxRewrite = TransactionRecoveryImpl.getTransactionRecovery().howlCommitLog(recoveryBuffer); 1190 } catch (Exception e) { 1191 status = Status.STATUS_UNKNOWN; 1193 1194 String howlerror = 1195 "Cannot howlCommitLog:" 1196 + e 1197 + " --" 1198 + e.getMessage(); 1199 TraceTm.jotm.error("Got LogException from howlCommitLog: "+ howlerror); 1200 xaCommitTx = null; 1201 1202 doAfterCompletion(); 1203 log.forgetLog(); 1204 1205 throw new TransactionRolledbackException(); 1206 } 1207 1208 status = Status.STATUS_UNKNOWN; 1210 1211 try { 1212 jotmDoneRecord [0] = jotmDone; 1213 TransactionRecoveryImpl.getTransactionRecovery().howlDoneLog(jotmDoneRecord, xaCommitTx); 1214 } catch (Exception f) { 1215 String howlerror = 1216 "Cannot howlDoneLog" 1217 + f 1218 + "--" 1219 + f.getMessage(); 1220 TraceTm.jotm.error("Got LogException from howlDoneLog: "+ howlerror); 1221 } 1222 } 1223 } 1224 1225 status = Status.STATUS_UNKNOWN; 1226 1227 doAfterCompletion(); 1228 return -1; 1229 } 1230 1231 1234 1235 private synchronized void doOnePhaseCommit() throws RemoteException { 1236 if (TraceTm.jta.isDebugEnabled()) { 1237 TraceTm.jta.debug("SubCoordinator.doOnePhaseCommit()"); 1238 } 1239 1240 1242 status = Status.STATUS_COMMITTING; 1243 1244 XAResource res = (XAResource ) resourceList.elementAt(0); 1245 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid ) javaxxidList.elementAt(0); 1246 Xid xid = new XidImpl( this.xid, 0 ); 1247 1248 if (TraceTm.jta.isDebugEnabled()) { 1249 TraceTm.jta.debug("xid= " + xid); 1250 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 1251 TraceTm.jta.debug("one phase commit with resource= " + res); 1252 } 1253 1254 try { 1255 res.commit(myjavaxxid, true); 1256 1258 Current.getCurrent().incrementCommitCounter(); 1260 status = Status.STATUS_COMMITTED; 1261 } catch (XAException e) { 1262 status = Status.STATUS_UNKNOWN; 1263 String error = 1264 "Cannot send res.commit:" 1265 + e 1266 + " (error code = " 1267 + e.errorCode 1268 + ") --" 1269 + e.getMessage(); 1270 TraceTm.jotm.error( 1271 "Got XAException from res.commit: "+ error); 1272 1273 if (e.errorCode == XAException.XA_RBROLLBACK) { 1274 throw new TransactionRolledbackException("XAException:"+ error); 1275 } 1276 throw new RemoteException ("XAException:"+ error); 1277 } finally { 1278 doAfterCompletion(); 1279 } 1280 } 1281 1282 1285 1286 private synchronized void doRollback() throws RemoteException { 1287 if (TraceTm.jta.isDebugEnabled()) { 1288 TraceTm.jta.debug("SubCoordinator.doRollback()"); 1289 } 1290 1291 status = Status.STATUS_ROLLEDBACK; 1292 boolean heurroll = false; 1293 String rberror = null; 1294 int errors = 0; 1295 1296 for (int i = 0; i < resourceList.size(); i++) { 1298 1299 XAResource res = (XAResource ) resourceList.elementAt(i); 1300 javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid ) javaxxidList.elementAt(i); 1301 Xid xid = new XidImpl( this.xid, i ); 1302 1303 if (TraceTm.jta.isDebugEnabled()) { 1304 TraceTm.jta.debug("xid= " + xid); 1305 TraceTm.jta.debug("myjavaxxid= " + myjavaxxid); 1306 TraceTm.jta.debug("rolled back with resource= " + res); 1307 } 1308 1309 1313 try { 1314 res.rollback(myjavaxxid); 1315 } catch (XAException e) { 1317 switch (e.errorCode) { 1318 case XAException.XA_HEURHAZ : 1319 case XAException.XA_HEURCOM : 1320 case XAException.XA_HEURRB : 1321 case XAException.XA_HEURMIX : 1322 if (TraceTm.jta.isDebugEnabled()) { 1323 TraceTm.jta.debug("Heuristic condition= " + e.getMessage()); 1324 } 1325 heurroll = true; 1326 case XAException.XAER_RMERR : 1327 case XAException.XAER_NOTA : 1328 case XAException.XAER_INVAL : 1329 case XAException.XAER_PROTO: 1330 case XAException.XAER_RMFAIL : 1331 if (TraceTm.jta.isDebugEnabled()) { 1332 TraceTm.jta.debug("RM error= " + e.getMessage()); 1333 } 1334 default : 1335 if (TraceTm.jta.isDebugEnabled()) { 1336 TraceTm.jta.debug("Default error= " + e.getMessage()); 1337 } 1338 } 1339 1340 rberror = 1341 "Cannot send res.rollback:" 1342 + e 1343 + " (error code = " 1344 + e.errorCode 1345 + ") --" 1346 + e.getMessage(); 1347 TraceTm.jotm.error( 1348 "Got XAException from res.rollback: "+ rberror); 1349 1350 errors++; 1351 } 1352 } 1353 1354 1356 if (heurroll) { 1357 throw new HeuristicRollback(); 1358 } 1359 1360 1362 if (errors != 0) { 1363 throw new RemoteException ("rollback: Unexpected XAException:"+ rberror); 1364 } 1365 1366 1368 Current.getCurrent().incrementRollbackCounter(); 1369 1370 doAfterCompletion(); 1371 1372 } 1373 1374 1379 1380 private void doBeforeCompletion(boolean committing) { 1381 if (TraceTm.jta.isDebugEnabled()) { 1382 TraceTm.jta.debug("doBeforeCompletion committing= "+ committing); 1383 } 1384 1385 if (beforeCompletionDone) 1386 return; 1387 1388 1390 tx.unsetTimer(); 1391 1392 1394 if (committing && synchroList.size() > 0) { 1395 1399 1401 Transaction mytx = null; 1402 boolean suspended = false; 1403 boolean resumed = false; 1404 1405 try { 1406 mytx = tm.getTransaction(); 1407 } catch (SystemException e) { 1408 if (TraceTm.jta.isDebugEnabled()) { 1409 String error = 1410 "Cannot get transaction:" 1411 + e 1412 + "--" 1413 + e.getMessage(); 1414 TraceTm.jta.debug(error); 1415 } 1416 } 1417 1418 1420 if (mytx != null && mytx.equals(tx) == false) { 1421 try { 1422 tm.suspend(); 1423 suspended = true; 1424 } catch (SystemException e) { 1425 if (TraceTm.jta.isDebugEnabled()) { 1426 String error = 1427 "Cannot suspend transaction:" 1428 + e 1429 + "--" 1430 + e.getMessage(); 1431 TraceTm.jta.debug(error); 1432 } 1433 } 1434 } 1435 1436 1438 if (mytx == null || suspended) { 1439 try { 1440 tm.resume(tx); 1441 resumed = true; 1442 } catch (SystemException e) { 1443 if (TraceTm.jta.isDebugEnabled()) { 1444 String error = 1445 "Cannot resume transaction:" 1446 + e 1447 + "--" 1448 + e.getMessage(); 1449 TraceTm.jta.debug(error); 1450 } 1451 } catch (InvalidTransactionException e) { 1452 if (TraceTm.jta.isDebugEnabled()) { 1453 String error = 1454 "Cannot resume transaction:" 1455 + e 1456 + "--" 1457 + e.getMessage(); 1458 TraceTm.jta.debug(error); 1459 } 1460 } catch (IllegalStateException e) { 1461 if (TraceTm.jta.isDebugEnabled()) { 1462 String error = 1463 "Cannot resume transaction:" 1464 + e 1465 + "--" 1466 + e.getMessage(); 1467 TraceTm.jta.debug(error); 1468 } 1469 } 1470 } 1471 1472 1475 if (TraceTm.jta.isDebugEnabled()) { 1476 TraceTm.jta.debug("sychronization list size= " + synchroList.size()); 1477 } 1478 1479 for (int i = 0; i < synchroList.size(); i++) { 1480 Synchronization sync = 1481 (Synchronization) synchroList.elementAt(i); 1482 1483 if (TraceTm.jta.isDebugEnabled()) { 1484 TraceTm.jta.debug("Synchronization sync= " + sync); 1485 } 1486 1487 sync.beforeCompletion(); 1488 } 1489 1490 1492 if (resumed) { 1493 try { 1494 tm.suspend(); 1495 } catch (SystemException e) { 1496 if (TraceTm.jta.isDebugEnabled()) { 1497 String error = 1498 "Cannot suspend transaction:" 1499 + e 1500 + "--" 1501 + e.getMessage(); 1502 TraceTm.jta.debug(error); 1503 } 1504 } 1505 } 1506 1507 if (suspended) { 1508 try { 1509 tm.resume(mytx); 1510 resumed = true; 1511 } catch (SystemException e) { 1512 if (TraceTm.jta.isDebugEnabled()) { 1513 String error = 1514 "Cannot resume transaction:" 1515 + e 1516 + "--" 1517 + e.getMessage(); 1518 TraceTm.jta.debug(error); 1519 } 1520 } catch (InvalidTransactionException e) { 1521 if (TraceTm.jta.isDebugEnabled()) { 1522 String error = 1523 "Cannot resume transaction:" 1524 + e 1525 + "--" 1526 + e.getMessage(); 1527 TraceTm.jta.debug(error); 1528 } 1529 } catch (IllegalStateException e) { 1530 if (TraceTm.jta.isDebugEnabled()) { 1531 String error = 1532 "Cannot resume transaction:" 1533 + e 1534 + "--" 1535 + e.getMessage(); 1536 TraceTm.jta.debug(error); 1537 } 1538 } 1539 } 1540 } 1541 1542 beforeCompletionDone = true; 1543 } 1544 1545 1548 1549 private void doAfterCompletion() { 1550 if (TraceTm.jta.isDebugEnabled()) { 1551 TraceTm.jta.debug("doAfterCompletion()"); 1552 } 1553 1554 1557 if (TraceTm.jta.isDebugEnabled()) { 1558 TraceTm.jta.debug("sychronization list size= "+ synchroList.size()); 1559 } 1560 1561 for (int i = 0; i < synchroList.size(); i++) { 1562 Synchronization sync = (Synchronization) synchroList.elementAt(i); 1563 1564 if (TraceTm.jta.isDebugEnabled()) { 1565 TraceTm.jta.debug("Synchronization sync= " + sync); 1566 TraceTm.jta.debug("sync.afterCompletion status= " + StatusHelper.getStatusName(status)); 1567 } 1568 1569 sync.afterCompletion(status); 1570 } 1571 1572 1577 Current.getCurrent().forgetTx(tx.getXid()); 1578 1579 if (TraceTm.jta.isDebugEnabled()) { 1580 TraceTm.jta.debug("SubCoordinator unexported [subcoord=" + this + "]"); 1581 } 1582 1583 try { 1584 unexportObject(this); 1585 } catch (Exception e) {} 1586 } 1587 1588 1592 public int getXaresIndex( XAResource xares ) { 1593 1594 if (TraceTm.jta.isDebugEnabled()) { 1595 TraceTm.jta.debug("getXaresIndex xares= "+ xares); 1596 TraceTm.jta.debug("resourceList.size= " + resourceList.size()); 1597 } 1598 1599 int xaresIndex = -1; 1600 1601 if (TraceTm.jta.isDebugEnabled()) { 1603 TraceTm.jta.debug("search xares with same obj ref"); 1604 } 1605 1606 for (int i = 0; i < resourceList.size(); i++ ) { 1607 XAResource res = (XAResource )resourceList.elementAt(i); 1608 1609 if (TraceTm.jta.isDebugEnabled()) { 1610 TraceTm.jta.debug("res= "+ res); 1611 } 1612 1613 if (res.equals(xares)) { 1614 xaresIndex = i; 1615 break; 1616 } 1617 } 1618 1619 if (xaresIndex == -1) { 1621 if (TraceTm.jta.isDebugEnabled()) { 1622 TraceTm.jta.debug("not found -> search for xares with same RM"); 1623 } 1624 1625 for (int i = 0; i < resourceList.size(); i++) { 1626 XAResource res = (XAResource ) resourceList.elementAt(i); 1627 1628 if (TraceTm.jta.isDebugEnabled()) { 1629 TraceTm.jta.debug("res= "+ res); 1630 } 1631 1632 try { 1633 if (res.isSameRM(xares) ) { 1634 xaresIndex = i; 1635 break; 1636 } 1637 } catch( XAException e ) { 1638 if (TraceTm.jta.isDebugEnabled()) { 1639 String error = 1640 "res.isSameRm exception:" 1641 + e 1642 + "--" 1643 + e.getMessage(); 1644 TraceTm.jta.debug(error); 1645 } 1646 } 1647 } 1648 } 1649 1650 if (TraceTm.jta.isDebugEnabled()) { 1651 TraceTm.jta.debug("xaresIndex= " + xaresIndex); 1652 } 1653 1654 return xaresIndex; 1655 } 1656 1657} 1658 | Popular Tags |