1 22 package org.jboss.tm.recovery; 23 24 import java.util.ArrayList ; 25 import java.util.Arrays ; 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.Set ; 32 33 import javax.transaction.Status ; 34 import javax.transaction.xa.XAException ; 35 import javax.transaction.xa.XAResource ; 36 import javax.transaction.xa.Xid ; 37 38 import org.jboss.logging.Logger; 39 import org.jboss.tm.TxManager; 40 import org.jboss.tm.TxUtils; 41 import org.jboss.tm.XidFactoryBase; 42 43 57 public class RecoveryManager 58 { 59 62 private static Logger log = Logger.getLogger(RecoveryManager.class.getName()); 63 64 71 public static class XAResourceAccessImpl 72 implements XAResourceAccess 73 { 74 private Recoverable recoverable; 75 private int refCount; 76 77 XAResourceAccessImpl(Recoverable recoverable) 79 { 80 this.recoverable = recoverable; 81 refCount = 1; 82 } 83 84 synchronized XAResourceAccess duplicate() 86 { 87 refCount++; 88 return this; 89 } 90 91 public synchronized void release() 92 { 93 if (refCount <= 0) 94 log.warn("release called, but refCount=" + refCount + 95 ", this=" + this, new Throwable ("[Stack trace]")); 96 97 if (--refCount == 0) 98 recoverable.cleanupResource(); 99 } 100 101 } 102 103 108 private static class XAResourceXids 109 { 110 public Recoverable recoverable; 111 public XAResource resource; 112 public XAResourceAccessImpl resourceAccess; 113 public Set xids; 114 115 XAResourceXids(Recoverable recoverable) 116 { 117 this.recoverable = recoverable; 118 this.resource = recoverable.getResource(); 119 this.resourceAccess = new XAResourceAccessImpl(recoverable); 122 this.xids = new HashSet (); 123 } 124 } 125 126 131 private static class CompletionHandler 132 implements TxCompletionHandler 133 { 134 138 private RecoveryLogReader reader; 139 140 143 private int pendingTransactions; 144 145 154 CompletionHandler(RecoveryLogReader reader, int pendingTransactions) 155 { 156 this.reader = reader; 157 this.pendingTransactions = pendingTransactions; 158 } 159 160 167 public void handleTxCompletion(long localTransactionId) 168 { 169 if (--pendingTransactions == 0) 170 reader.finishRecovery(); 171 } 172 } 173 174 177 private XidFactoryBase xidFactory; 178 179 182 private TxManager txManager; 183 184 187 private RecoveryLogger recoveryLogger; 188 189 199 public RecoveryManager(XidFactoryBase xidFactory, 200 TxManager txManager, 201 RecoveryLogger recoveryLogger) 202 { 203 this.xidFactory = xidFactory; 204 this.txManager = txManager; 205 this.recoveryLogger = recoveryLogger; 206 } 207 208 219 public void recover(ArrayList recoverables) 220 { 221 Map heuristicallyCompletedTransactions = new HashMap (); 222 223 HeuristicStatusLogReader[] heurStatusLogReaders = 224 recoveryLogger.getHeuristicStatusLogs(); 225 226 if (heurStatusLogReaders != null) 227 { 228 for (int i = 0; i < heurStatusLogReaders.length; i++) 231 heurStatusLogReaders[i].recover(heuristicallyCompletedTransactions); 232 233 Iterator heurIt = 236 heuristicallyCompletedTransactions.keySet().iterator(); 237 while (heurIt.hasNext()) 238 { 239 Long localId = (Long ) heurIt.next(); 240 LogRecord.HeurData heurData = 241 (LogRecord.HeurData) heuristicallyCompletedTransactions.get( 242 localId); 243 recoveryLogger.saveHeuristicStatus( 244 heurData.localTransactionId, 245 heurData.foreignTx, 246 heurData.formatId, 247 heurData.globalTransactionId, 248 heurData.inboundBranchQualifier, 249 heurData.transactionStatus, 250 heurData.heuristicStatusCode, 251 heurData.locallyDetectedHeuristicHazard, 252 heurData.xaResourceHeuristics, 253 heurData.remoteResourceHeuristics); 254 } 255 256 for (int i = 0; i < heurStatusLogReaders.length; i++) 258 heurStatusLogReaders[i].finishRecovery(); 259 } 260 261 RecoveryLogReader[] readers = recoveryLogger.getRecoveryLogs(); 262 if (readers == null || readers.length == 0) 263 return; 264 265 Set readerBranchQualifiers = new HashSet (); 267 for (int i = 0; i < readers.length; i++) 268 { 269 String branchQualifier = null; 270 try 271 { 272 branchQualifier = readers[i].getBranchQualifier(); 273 } 274 catch (Exception e) 275 { 276 log.error("logfile corrupted: " 277 + readers[i].getLogFileName(), e); 278 } 279 readerBranchQualifiers.add(branchQualifier); 280 log.info("will recover transactions with branch qualifier " + 281 branchQualifier + 282 " (logFile: " + readers[i].getLogFileName() + ")"); 283 } 284 285 Map toRecoverMap = new HashMap (); 286 try 287 { 288 for (int i = 0; i < recoverables.size(); i++) 293 { 294 Recoverable rec = (Recoverable) recoverables.get(i); 295 XAResourceXids xaResXids; 296 try 297 { 298 xaResXids = new XAResourceXids(rec); 299 } 300 catch (Throwable t) 301 { 302 throw new RuntimeException ("Unable to getResource: " 303 + rec.getId() 304 + " aborting recovery.", t); 305 } 306 toRecoverMap.put(rec.getId(), xaResXids); 307 try 308 { 309 xaResXids.xids.addAll(pruneXidList(rec.scan(), 310 readerBranchQualifiers, 311 rec.getId())); 312 } 313 catch (XAException e) 314 { 315 throw new RuntimeException ("Unable to scan: " + rec.getId(), e); 318 } 319 } 320 321 recover(readers, heuristicallyCompletedTransactions, toRecoverMap); 323 } 324 finally 325 { 326 cleanupRecoverables(toRecoverMap.values().iterator()); 327 } 328 } 329 330 344 private void recover(RecoveryLogReader[] readers, 345 Map heuristicallyCompletedTransactions, 346 Map toRecoverMap) 347 { 348 boolean presumeRollback = true; 349 CorruptedLogRecordException corruptedLogRecordException = null; 350 351 for (int i = 0; i < readers.length; i++) 354 { 355 log.info("recovering log file " + readers[i].getLogFileName()); 356 List committedSingleTmTransactions = new ArrayList (); 357 List committedMultiTmTransactions = new ArrayList (); 358 List inDoubtTransactions = new ArrayList (); 359 List inDoubtJcaTransactions = new ArrayList (); 360 361 try 362 { 363 readers[i].recover(committedSingleTmTransactions, 364 committedMultiTmTransactions, 365 inDoubtTransactions, 366 inDoubtJcaTransactions); 367 } 368 catch (CorruptedLogRecordException e) 369 { 370 log.trace("reader threw CorruptedLogRecordException with " + 371 "disablePresumedRollback=" + e.disablePresumedRollback); 372 corruptedLogRecordException = e; 373 if (corruptedLogRecordException.disablePresumedRollback) 374 presumeRollback = false; 375 } 376 377 int pendingTransactions = committedSingleTmTransactions.size() + 378 committedMultiTmTransactions.size() + 379 inDoubtTransactions.size() + 380 inDoubtJcaTransactions.size(); 381 382 if (pendingTransactions == 0) 383 readers[i].finishRecovery(); 384 else 385 { 386 CompletionHandler completionHandler = 387 new CompletionHandler(readers[i], pendingTransactions); 388 389 resumePendingTransactions(heuristicallyCompletedTransactions, 390 committedSingleTmTransactions, 391 committedMultiTmTransactions, 392 inDoubtTransactions, 393 inDoubtJcaTransactions, 394 toRecoverMap, 395 completionHandler); 396 } 397 } 398 399 Iterator heurIt = heuristicallyCompletedTransactions.keySet().iterator(); 402 while (heurIt.hasNext()) 403 { 404 Long localId = (Long ) heurIt.next(); 405 LogRecord.HeurData heurData = 406 (LogRecord.HeurData) heuristicallyCompletedTransactions.get(localId); 407 heurIt.remove(); byte[] globalId = heurData.globalTransactionId; 409 List xaResourcesWithHeuristics = getXAWork(globalId, toRecoverMap); 410 txManager.recreateTransaction(heurData, 411 xaResourcesWithHeuristics, 412 null ); 413 } 414 415 if (!presumeRollback) 416 { 417 log.info("PRESUMED ROLLBACK IS DISABLED DUE TO LOG FILE CORRUPTION."); 418 } 419 420 Iterator rit = toRecoverMap.values().iterator(); 423 while (rit.hasNext()) 424 { 425 XAResourceXids xaResXids = (XAResourceXids) rit.next(); 426 Iterator it = xaResXids.xids.iterator(); 427 while (it.hasNext()) 428 { 429 Xid xid = (Xid ) it.next(); 430 if (!presumeRollback) 431 { 432 log.info("WOULD ROLLBACK " + xidFactory.toString(xid) + 433 " ON RECOVERABLE XAResource " + 434 xaResXids.recoverable.getId() + 435 ", BUT PRESUMED ROLLBACK IS DISABLED"); 436 } 437 else 438 { 439 try 440 { 441 xaResXids.resource.rollback(xid); 442 log.info("rolledback " + xidFactory.toString(xid) + 443 " on recoverable XAResource " + 444 xaResXids.recoverable.getId()); 445 } 446 catch (XAException e) 447 { 448 log.warn("XAException in recover (when rolling back " + 449 "res " + xaResXids.recoverable.getId() + ", xid=" + 450 xidFactory.toString(xid) + "): errorCode=" 451 + TxUtils.getXAErrorCodeAsString(e.errorCode), e); 452 } 455 } 456 } 457 } 458 459 if (corruptedLogRecordException != null) 460 throw corruptedLogRecordException; 461 } 462 463 492 private void resumePendingTransactions(Map heuristicallyCompletedTransactions, 493 List committedSingleTmTransactions, 494 List committedMultiTmTransactions, 495 List inDoubtTransactions, 496 List inDoubtJcaTransactions, 497 Map toRecoverMap, 498 TxCompletionHandler completionHandler) 499 { 500 Iterator it; 501 LogRecord.Data data; 502 LogRecord.HeurData heurData; 503 504 it = committedSingleTmTransactions.iterator(); 505 while (it.hasNext()) 506 { 507 data = (LogRecord.Data) it.next(); 508 byte[] globalId = data.globalTransactionId; 509 Long localId = new Long (data.localTransactionId); 510 heurData = 511 (LogRecord.HeurData)heuristicallyCompletedTransactions.get(localId); 512 513 if (heurData != null) 514 heuristicallyCompletedTransactions.remove(localId); 515 516 if (heurData != null && !heurData.locallyDetectedHeuristicHazard) 517 { 518 List xaResourcesWithHeuristics = getXAWork(globalId, toRecoverMap); 519 txManager.recreateTransaction(heurData, 520 xaResourcesWithHeuristics, 521 completionHandler); 522 } 523 else 524 { 525 528 List pendingXAWorkList = commitXAWork(globalId, toRecoverMap); 529 if (pendingXAWorkList.isEmpty()) 530 { 531 if (heurData == null) 532 { 533 completionHandler.handleTxCompletion(data.localTransactionId); 534 } 535 else 536 { 537 txManager.recreateTransaction(heurData, 539 pendingXAWorkList, 540 completionHandler); 541 } 542 } 543 else 544 { 545 txManager.recreateTransaction(data.localTransactionId, 546 pendingXAWorkList, 547 completionHandler, 548 heurData); 549 } 550 } 551 } 552 553 it = committedMultiTmTransactions.iterator(); 554 while (it.hasNext()) 555 { 556 data = (LogRecord.Data) it.next(); 557 byte[] globalId = data.globalTransactionId; 558 Long localId = new Long (data.localTransactionId); 559 heurData = 560 (LogRecord.HeurData)heuristicallyCompletedTransactions.get(localId); 561 562 if (heurData != null) 563 heuristicallyCompletedTransactions.remove(localId); 564 565 if (heurData != null && !heurData.locallyDetectedHeuristicHazard) 566 { 567 List xaResourcesWithHeuristics = getXAWork(globalId, toRecoverMap); 568 txManager.recreateTransaction(heurData, 569 xaResourcesWithHeuristics, 570 completionHandler); 571 } 572 else 573 { 574 577 List pendingXAWorkList = commitXAWork(globalId, toRecoverMap); 578 txManager.recreateTransaction(data.localTransactionId, 579 pendingXAWorkList, 580 data.resources, 581 completionHandler, 582 heurData); 583 } 584 } 585 586 it = inDoubtTransactions.iterator(); 587 while (it.hasNext()) 588 { 589 data = (LogRecord.Data) it.next(); 590 byte[] globalId = data.globalTransactionId; 591 Long localId = new Long (data.localTransactionId); 592 heurData = 593 (LogRecord.HeurData)heuristicallyCompletedTransactions.get(localId); 594 595 if (heurData != null) 596 heuristicallyCompletedTransactions.remove(localId); 597 598 if (heurData != null && !heurData.locallyDetectedHeuristicHazard) 599 { 600 heuristicallyCompletedTransactions.remove(localId); 601 List xaResourcesWithHeuristics = getXAWork(globalId, toRecoverMap); 602 txManager.recreateTransaction(heurData, 603 xaResourcesWithHeuristics, 604 completionHandler); 605 } 606 else 607 { 608 611 if (heurData == null) 612 { 613 List preparedXAWorkList = getXAWork(globalId, toRecoverMap); 614 txManager.recreateTransaction(data.localTransactionId, 615 data.inboundFormatId, 616 data.globalTransactionId, 617 data.recoveryCoordinator, 618 preparedXAWorkList, 619 data.resources, 620 completionHandler, 621 null); 622 } 623 else 624 { 625 if (heurData.transactionStatus == Status.STATUS_COMMITTING) 627 { 628 List pendingXAWorkList = commitXAWork(globalId, toRecoverMap); 629 txManager.recreateTransaction(data.localTransactionId, 630 data.inboundFormatId, 631 data.globalTransactionId, 632 data.recoveryCoordinator, 633 pendingXAWorkList, 634 data.resources, 635 completionHandler, 636 heurData); 637 } 638 else if (heurData.transactionStatus == Status.STATUS_ROLLING_BACK) 639 { 640 List pendingXAWorkList = 641 rollbackXAWork(globalId, toRecoverMap); 642 txManager.recreateTransaction(data.localTransactionId, 643 data.inboundFormatId, 644 data.globalTransactionId, 645 data.recoveryCoordinator, 646 pendingXAWorkList, 647 data.resources, 648 completionHandler, 649 heurData); 650 } 651 else 652 { 653 log.warn("Cannot recover tx=" + toString() + 654 "\nInconsistent state", 655 new Throwable ("[Stack trace]")); 656 } 657 } 658 } 659 } 660 661 it = inDoubtJcaTransactions.iterator(); 662 while (it.hasNext()) 663 { 664 data = (LogRecord.Data) it.next(); 665 byte[] globalId = data.globalTransactionId; 666 Long localId = new Long (data.localTransactionId); 667 heurData = 668 (LogRecord.HeurData)heuristicallyCompletedTransactions.get(localId); 669 670 if (heurData != null) 671 heuristicallyCompletedTransactions.remove(localId); 672 673 if (heurData != null && !heurData.locallyDetectedHeuristicHazard) 674 { 675 List xaResourcesWithHeuristics = getXAWork(globalId, toRecoverMap); 676 txManager.recreateTransaction(heurData, 677 xaResourcesWithHeuristics, 678 completionHandler); 679 } 680 else 681 { 682 685 List preparedXAWorkList = getXAWork(globalId, toRecoverMap); 686 if (heurData == null) 687 { 688 txManager.recreateTransaction(data.localTransactionId, 689 data.inboundFormatId, 690 data.globalTransactionId, 691 data.inboundBranchQualifier, 692 preparedXAWorkList, 693 data.resources, 694 completionHandler, 695 null); 696 } 697 else 698 { 699 if (heurData.transactionStatus == Status.STATUS_COMMITTING) 701 { 702 List pendingXAWorkList = commitXAWork(globalId, toRecoverMap); 703 txManager.recreateTransaction(data.localTransactionId, 704 data.inboundFormatId, 705 data.globalTransactionId, 706 data.inboundBranchQualifier, 707 pendingXAWorkList, 708 data.resources, 709 completionHandler, 710 heurData); 711 } 712 else if (heurData.transactionStatus == Status.STATUS_ROLLING_BACK) 713 { 714 List pendingXAWorkList = 715 rollbackXAWork(globalId, toRecoverMap); 716 txManager.recreateTransaction(data.localTransactionId, 717 data.inboundFormatId, 718 data.globalTransactionId, 719 data.inboundBranchQualifier, 720 pendingXAWorkList, 721 data.resources, 722 completionHandler, 723 heurData); 724 } 725 else 726 { 727 log.warn("Cannot recover tx=" + toString() + 728 "\nInconsistent state", 729 new Throwable ("[Stack trace]")); 730 } 731 } 732 } 733 } 734 } 735 736 758 private List commitXAWork(byte[] globalId, Map toRecoverMap) 759 { 760 log.info("*** trying to complete XA work with globalId " + 761 new String (globalId).trim()); 762 globalId = pad(globalId); 763 List pendingXAWorkList = new ArrayList (); 764 Iterator rit = toRecoverMap.values().iterator(); 765 while (rit.hasNext()) 766 { 767 XAResourceXids toRecover = (XAResourceXids) rit.next(); 768 log.info(" looking at resource " + toRecover.recoverable.getId()); 769 770 Iterator resXidIt = toRecover.xids.iterator(); 771 while (resXidIt.hasNext()) 772 { 773 Xid resXid = (Xid ) resXidIt.next(); 774 byte[] resGlobalId = pad(resXid.getGlobalTransactionId()); 775 if (!Arrays.equals(globalId, resGlobalId)) 776 continue; 777 try 778 { 779 toRecover.resource.commit(resXid, false); 780 log.info(" committed: " + resXid); 781 } 782 catch (XAException e) 783 { 784 switch (e.errorCode) 785 { 786 case XAException.XA_HEURCOM: 787 log.trace("commitXAWork ignored XAException.XA_HEURCOM", e); 790 try 791 { 792 toRecover.resource.forget(resXid); 793 } 794 catch (XAException xae) 795 { 796 log.warn("XAException in commitXAWork (when forgetting " + 797 "XA_HEURCOM): errorCode=" + 798 TxUtils.getXAErrorCodeAsString(xae.errorCode), 799 xae); 800 } 801 break; 802 case XAException.XA_HEURRB: 803 case XAException.XA_HEURMIX: 804 case XAException.XA_HEURHAZ: 805 log.warn("Heuristic XAException in commitXAWork: errorCode=" + 806 TxUtils.getXAErrorCodeAsString(e.errorCode) + 807 "\nWill deal with the heuristic later", e); 808 XAWork postponedWork = new XAWork(toRecover.resource, 809 resXid, 810 toRecover.resourceAccess); 811 pendingXAWorkList.add(postponedWork); 812 break; 813 case XAException.XAER_RMERR: 814 log.warn("Unexpected XAException in commitXAWork: errorCode=" 815 + TxUtils.getXAErrorCodeAsString(e.errorCode), e); 816 break; 817 case XAException.XAER_RMFAIL: 818 case XAException.XA_RETRY: 819 log.warn("XAException in commitXAWork: errorCode=" + 820 TxUtils.getXAErrorCodeAsString(e.errorCode) + 821 "\nWill attempt to commit the XAResource later", e); 822 XAWork pendingXAWork = new XAWork(toRecover.resource, 823 resXid, 824 toRecover.resourceAccess); 825 pendingXAWorkList.add(pendingXAWork); 826 break; 827 case XAException.XAER_NOTA: 828 case XAException.XAER_INVAL: 829 case XAException.XAER_PROTO: 830 default: 831 log.warn("Could not recover from unexpected XAException: " + 833 " errorCode=" + 834 TxUtils.getXAErrorCodeAsString(e.errorCode), e); 835 break; 836 } 837 } 838 finally 839 { 840 resXidIt.remove(); } 842 } 843 if (toRecover.xids.isEmpty()) 844 rit.remove(); } 846 return pendingXAWorkList; 847 } 848 849 private List rollbackXAWork(byte[] globalId, Map toRecoverMap) 850 { 851 log.info("*** trying to rollback XA work with globalId " + 852 new String (globalId).trim()); 853 globalId = pad(globalId); 854 List pendingXAWorkList = new ArrayList (); 855 Iterator rit = toRecoverMap.values().iterator(); 856 while (rit.hasNext()) 857 { 858 XAResourceXids toRecover = (XAResourceXids) rit.next(); 859 log.info(" looking at resource " + toRecover.recoverable.getId()); 860 861 Iterator resXidIt = toRecover.xids.iterator(); 862 while (resXidIt.hasNext()) 863 { 864 Xid resXid = (Xid ) resXidIt.next(); 865 byte[] resGlobalId = pad(resXid.getGlobalTransactionId()); 866 if (!Arrays.equals(globalId, resGlobalId)) 867 continue; 868 try 869 { 870 toRecover.resource.rollback(resXid); 871 log.info(" rolledback: " + resXid); 872 } 873 catch (XAException e) 874 { 875 switch (e.errorCode) 876 { 877 case XAException.XA_HEURRB: 878 log.trace("rollbackXAWork ignored XAException.XA_HEURRB", e); 881 try 882 { 883 toRecover.resource.forget(resXid); 884 } 885 catch (XAException xae) 886 { 887 log.warn("XAException in rollbackXAWork (when forgetting " 888 + "XA_HEURRB): errorCode=" + 889 TxUtils.getXAErrorCodeAsString(xae.errorCode), 890 xae); 891 } 892 break; 893 case XAException.XA_HEURCOM: 894 case XAException.XA_HEURMIX: 895 case XAException.XA_HEURHAZ: 896 log.warn("Heuristic XAException in rollbackXAWork: errorCode=" 897 + TxUtils.getXAErrorCodeAsString(e.errorCode) + 898 "\nWill deal with the heuristic later", e); 899 XAWork postponedWork = new XAWork(toRecover.resource, 900 resXid, 901 toRecover.resourceAccess); 902 pendingXAWorkList.add(postponedWork); 903 break; 904 case XAException.XAER_RMERR: 905 log.warn("Unexpected XAException in rollbackXAWork: " + 906 "errorCode=" 907 + TxUtils.getXAErrorCodeAsString(e.errorCode), e); 908 break; 909 case XAException.XAER_RMFAIL: 910 case XAException.XA_RETRY: 911 log.warn("XAException in rollbackXAWork: errorCode=" + 912 TxUtils.getXAErrorCodeAsString(e.errorCode) + 913 "\nWill attempt to rollback the XAResource later", e); 914 XAWork pendingXAWork = new XAWork(toRecover.resource, 915 resXid, 916 toRecover.resourceAccess); 917 pendingXAWorkList.add(pendingXAWork); 918 break; 919 case XAException.XAER_NOTA: 920 case XAException.XAER_INVAL: 921 case XAException.XAER_PROTO: 922 default: 923 log.warn("Could not recover from unexpected XAException: " + 925 " errorCode=" + 926 TxUtils.getXAErrorCodeAsString(e.errorCode), e); 927 break; 928 } 929 } 930 finally 931 { 932 resXidIt.remove(); } 934 } 935 if (toRecover.xids.isEmpty()) 936 rit.remove(); } 938 return pendingXAWorkList; 939 } 940 941 961 private List getXAWork(byte[] globalId, Map toRecoverMap) 962 { 963 log.info("*** getting XA work with globalId " + 964 new String (globalId).trim()); 965 globalId = pad(globalId); 966 List xaWorkList = new ArrayList (); 967 Iterator rit = toRecoverMap.values().iterator(); 968 while (rit.hasNext()) 969 { 970 XAResourceXids toRecover = (XAResourceXids) rit.next(); 971 log.info(" looking at resource " + toRecover.recoverable.getId()); 972 973 Iterator resXidIt = toRecover.xids.iterator(); 974 while (resXidIt.hasNext()) 975 { 976 Xid resXid = (Xid ) resXidIt.next(); 977 byte[] resGlobalId = pad(resXid.getGlobalTransactionId()); 978 if (!Arrays.equals(globalId, resGlobalId)) 979 continue; 980 981 XAWork preparedXAWork = new XAWork(toRecover.resource, 982 resXid, 983 toRecover.resourceAccess); 984 xaWorkList.add(preparedXAWork); 985 resXidIt.remove(); } 987 } 988 return xaWorkList; 989 } 990 991 996 private void cleanupRecoverables(Iterator it) 997 { 998 while (it.hasNext()) 999 { 1000 XAResourceXids xaResXids = (XAResourceXids) it.next(); 1001 try 1002 { 1003 xaResXids.resourceAccess.release(); 1004 } 1005 catch (Exception ignored) 1006 { 1007 } 1008 } 1009 } 1010 1011 1016 private List pruneXidList(Xid [] xids, 1017 Set branchQualifiers, 1018 String resourceName) 1019 { 1020 ArrayList list = new ArrayList (); 1021 for (int i = 0; i < xids.length; i++) 1022 { 1023 byte[] branchQual = xids[i].getBranchQualifier(); 1024 String baseBranchQual = xidFactory.getBaseBranchQualifier(branchQual); 1025 if (branchQualifiers.contains(baseBranchQual)) 1026 { 1027 list.add(xids[i]); 1028 log.info("Adding xid " + xidFactory.toString(xids[i]) + 1029 " to pruned Xid list for " + resourceName); 1030 1031 } 1032 } 1033 return list; 1034 } 1035 1036 1042 private byte[] pad(byte[] globalId) 1043 { 1044 if (globalId.length < Xid.MAXGTRIDSIZE) 1045 { 1046 byte[] bytes = new byte[Xid.MAXGTRIDSIZE]; 1047 System.arraycopy(globalId, 0, bytes, 0, globalId.length); 1048 globalId = bytes; 1049 } 1050 return globalId; 1051 } 1052 1053} 1054 | Popular Tags |