| 1 47 package org.objectweb.jotm; 48 49 import java.rmi.RemoteException ; 50 import java.rmi.NoSuchObjectException ; 51 import java.rmi.ServerException ; 52 53 import javax.rmi.PortableRemoteObject ; 54 55 import java.util.List ; 56 import java.util.ArrayList ; 57 import javax.transaction.Status ; 58 import javax.transaction.TransactionRolledbackException ; 59 import javax.transaction.xa.Xid ; 60 61 import org.objectweb.carol.util.configuration.ConfigurationRepository; 62 import org.objectweb.carol.rmi.exception.RmiUtility; 63 64 72 public class ControlImpl 73 extends PortableRemoteObject  74 implements Control, Resource, Coordinator, Terminator , RecoveryCoordinator, TimerEventListener { 75 76 82 private List resourceList = new ArrayList (); 83 86 private List synchronizationList = new ArrayList (); 87 90 private int mystatus = Status.STATUS_UNKNOWN; 91 94 private boolean hasSupCoord = false; 95 98 private TimerEvent mytimer = null; 99 102 private Xid xid; 103 106 private Log mylog; 107 108 112 120 ControlImpl(int timeout, Xid x, Object supco) throws RemoteException { 121 if (TraceTm.jotm.isDebugEnabled()) { 122 TraceTm.jotm.debug("timeout="+ timeout +", xid="+ x +", supco="+ supco); 123 } 124 125 mystatus = Status.STATUS_ACTIVE; 127 xid = x; 128 hasSupCoord = (supco != null); 129 130 132 mytimer = TimerManager.getInstance().addTimer(this, timeout, new Integer (1), false); 133 134 if (supco != null) { 136 try { 137 if (supco instanceof Coordinator) 138 ((Coordinator) supco).register_resource(this); 139 else 140 throw new RemoteException ("Not Implemented"); 144 } catch (Exception e) { 145 TraceTm.jotm.error("Cannot register sub-coordinator:\n", e); 146 } 147 } 148 } 149 150 154 159 public Terminator get_terminator() throws RemoteException { 160 161 return this; 162 } 163 164 169 public Coordinator get_coordinator() throws RemoteException { 170 if (TraceTm.jotm.isDebugEnabled()) { 171 TraceTm.jotm.debug("ControlImpl.get_coordinator"); 172 } 173 return this; 174 } 175 176 180 185 public int get_status() throws RemoteException { 186 if (TraceTm.jotm.isDebugEnabled()) { 187 TraceTm.jotm.debug("ControlImpl.get_status()"); 188 } 189 return mystatus; 190 } 191 192 198 public boolean is_same_transaction(Coordinator tc) throws RemoteException { 199 if (TraceTm.jotm.isDebugEnabled()) { 200 TraceTm.jotm.debug("ControlImpl.is_same_transaction(Coordinator)"); 201 } 202 203 String other = null; 204 205 try { 206 other = tc.get_transaction_name(); 207 } catch (Exception e) { 208 if (TraceTm.jotm.isDebugEnabled()) { 209 TraceTm.jotm.error("ControlImpl.is_same_transaction() raised exception:\n", e); 210 } 211 return false; 212 } 213 214 return other.equals(get_transaction_name()); 215 } 216 217 223 public synchronized RecoveryCoordinator register_resource(Resource res) throws RemoteException { 224 if (TraceTm.jotm.isDebugEnabled()) { 225 TraceTm.jotm.debug("resource="+ res); 226 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 227 } 228 229 switch (mystatus) { 230 231 case Status.STATUS_ACTIVE : 232 resourceList.add(res); 234 if (TraceTm.jotm.isDebugEnabled()) { 235 TraceTm.jotm.debug("Resource registered"); 236 } 237 break; 238 239 case Status.STATUS_MARKED_ROLLBACK : 240 case Status.STATUS_ROLLEDBACK : 241 case Status.STATUS_ROLLING_BACK : 242 TraceTm.jotm.error("ControlImpl.register_resource(): Transaction Rolled back"); 243 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 244 throw new TransactionRolledbackException (); 245 246 default : 247 TraceTm.jotm.error("ControlImpl.register_resource(): Transaction Inactive"); 248 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 249 throw new InactiveException("Cannot register resource, status " + StatusHelper.getStatusName(mystatus)); 250 } 251 return this; 252 } 253 254 259 public synchronized void register_synchronization(RemoteSynchro sync) throws RemoteException { 260 if (TraceTm.jotm.isDebugEnabled()) { 261 TraceTm.jotm.debug("sync="+ sync); 262 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 263 } 264 265 switch (mystatus) { 266 267 case Status.STATUS_ACTIVE : 268 synchronizationList.add(sync); 270 if (TraceTm.jotm.isDebugEnabled()) { 271 TraceTm.jotm.debug("ControlImpl.register_synchronization(): RemoteSynchro registered"); 272 } 273 break; 274 275 case Status.STATUS_MARKED_ROLLBACK : 276 case Status.STATUS_ROLLEDBACK : 277 case Status.STATUS_ROLLING_BACK : 278 TraceTm.jotm.error("ControlImpl.register_synchronization(): Transaction Rolled back"); 279 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 280 throw new TransactionRolledbackException (); 281 282 default : 283 TraceTm.jotm.error("ControlImpl.register_synchronization(): Transaction Inactive"); 284 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 285 throw new InactiveException("Cannot register synchronization, status " + StatusHelper.getStatusName(mystatus)); 286 } 287 } 288 289 293 public synchronized void rollback_only() throws RemoteException { 294 if (TraceTm.jotm.isDebugEnabled()) { 295 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 296 } 297 298 switch (mystatus) { 299 300 case Status.STATUS_MARKED_ROLLBACK : 301 if (TraceTm.jotm.isDebugEnabled()) { 303 TraceTm.jotm.debug("ControlImpl.rollback_only(): Already marked rolledback"); 304 } 305 break; 306 307 case Status.STATUS_ACTIVE : 308 mystatus = Status.STATUS_MARKED_ROLLBACK; 310 if (TraceTm.jotm.isDebugEnabled()) { 311 TraceTm.jotm.debug("ControlImpl.rollback_only(): Marked rollback"); 312 } 313 break; 314 315 default : 316 TraceTm.jotm.error("ControlImpl.rollback_only(): Inactive"); 318 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 319 throw new InactiveException("Cannot rollback transaction, status " + StatusHelper.getStatusName(mystatus)); 320 } 321 } 322 323 330 public String get_transaction_name() throws RemoteException { 331 if (TraceTm.jotm.isDebugEnabled()) { 332 TraceTm.jotm.debug("ControlImpl.get_transaction_name()"); 333 } 334 335 return xid.toString(); 336 } 337 338 342 351 public synchronized void commit(boolean report_heuristics) throws RemoteException { 352 if (TraceTm.jotm.isDebugEnabled()) { 353 TraceTm.jotm.debug("report_heuristics="+ report_heuristics); 354 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 355 } 356 357 String protocol = ConfigurationRepository.getCurrentConfiguration().getProtocol().getName(); 358 359 if (mytimer != null) { 361 mytimer.stop(); 362 } 363 364 switch (mystatus) { 366 367 case Status.STATUS_ACTIVE : 368 break; 370 371 case Status.STATUS_COMMITTED : 372 TraceTm.jotm.error("ControlImpl.commit(boolean): already done"); 373 return; 374 375 case Status.STATUS_ROLLEDBACK : 376 TraceTm.jotm.error("ControlImpl.commit(boolean): already rolled back"); 377 completed(true); 380 381 if (protocol == null || !(protocol.equals("iiop"))) { 382 throw new TransactionRolledbackException (); 383 } 384 385 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 386 387 case Status.STATUS_MARKED_ROLLBACK : 388 int errors = do_before_completion(); 390 391 if (errors > 0) { 392 TraceTm.jotm.info("ControlImpl.commit(boolean): before completion error at rollback"); 393 } 394 395 do_rollback(report_heuristics); 396 completed(true); 397 398 if (protocol == null || !(protocol.equals("iiop"))) { 399 throw new TransactionRolledbackException (); 400 } 401 402 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 403 404 default : 405 TraceTm.jotm.error("ControlImpl.commit(boolean): bad status"); 406 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 407 408 if (protocol == null || !(protocol.equals("iiop"))) { 409 throw new HeuristicMixed(); 410 } 411 412 RmiUtility.rethrowRmiException(new HeuristicMixed()); 413 } 414 415 if (resourceList.size() == 1) { 418 TraceTm.jotm.debug("1 resource"); 419 420 int errors = do_before_completion(); 422 423 if (errors > 0) { 424 TraceTm.jotm.info("before completion error -> rollback"); 425 do_rollback(report_heuristics); 426 completed(true); 427 428 if (protocol == null || !(protocol.equals("iiop"))) { 429 throw new TransactionRolledbackException (); 430 } 431 432 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 433 } 434 435 mystatus = Status.STATUS_COMMITTING; 436 437 try { 438 Resource res = (Resource) resourceList.get(0); 439 res.commit_one_phase(); 440 mystatus = Status.STATUS_COMMITTED; 441 } catch (TransactionRolledbackException e) { 442 TraceTm.jotm.info("commit_one_phase = TransactionRolledbackException"); 443 mystatus = Status.STATUS_ROLLEDBACK; 444 } catch (HeuristicHazard e) { 445 TraceTm.jotm.info("commit_one_phase = HeuristicException"); 446 mystatus = Status.STATUS_UNKNOWN; 447 } catch (NoSuchObjectException e) { 448 TraceTm.jotm.info("commit_one_phase = NoSuchObjectException"); 450 mystatus = Status.STATUS_ROLLEDBACK; 451 } catch (ServerException e) { TraceTm.jotm.info("commit_one_phase = ServerException: "+ e); 453 mystatus = Status.STATUS_ROLLEDBACK; 454 } catch (Exception e) { 455 TraceTm.jotm.error("commit_one_phase = Unexpected exception: ", e); 456 mystatus = Status.STATUS_UNKNOWN; 457 } 458 459 do_after_completion(); 461 462 switch (mystatus) { 464 case Status.STATUS_COMMITTED : 465 completed(true); 466 break; 467 case Status.STATUS_ROLLEDBACK : 468 completed(true); 469 470 if (protocol == null || !(protocol.equals("iiop"))) { 471 throw new TransactionRolledbackException (); 472 } 473 474 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 475 case Status.STATUS_UNKNOWN : 476 completed(false); 477 478 if (report_heuristics) { 479 if (protocol == null || !(protocol.equals("iiop"))) { 480 throw new HeuristicHazard(); 481 } 482 483 RmiUtility.rethrowRmiException(new HeuristicHazard()); 484 } 485 } 486 return; 487 } 488 489 int v = do_prepare(report_heuristics); 491 492 if (TraceTm.jotm.isDebugEnabled()) { 493 TraceTm.jotm.debug("Vote = " + v); 494 } 495 496 switch (v) { 498 case Resource.VOTE_COMMIT : 499 if (TraceTm.jotm.isDebugEnabled()) { 500 TraceTm.jotm.debug("ControlImpl.commit(boolean): committing Tx"); 501 } 502 break; 503 case Resource.VOTE_ROLLBACK : 504 if (TraceTm.jotm.isDebugEnabled()) { 505 TraceTm.jotm.debug("ControlImpl.commit(boolean): rolling back Tx"); 506 } 507 do_rollback(report_heuristics); 508 completed(true); 509 510 if (protocol == null || !(protocol.equals("iiop"))) { 511 throw new TransactionRolledbackException (); 512 } 513 514 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 515 case Resource.VOTE_READONLY : 516 if (TraceTm.jotm.isDebugEnabled()) { 518 TraceTm.jotm.debug("ControlImpl.commit(boolean): readonly resources"); 519 } 520 mystatus = Status.STATUS_COMMITTED; 521 completed(true); 522 return; 523 } 524 525 mylog.flushLog(Log.DECISION_TO_COMMIT); 527 528 if (do_commit(report_heuristics) == 0) { 530 completed(true); 531 } else { 532 completed(false); 533 } 534 } 535 536 541 546 public synchronized void rollback() throws RemoteException { 547 if (TraceTm.jotm.isDebugEnabled()) { 548 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 549 } 550 551 String protocol = ConfigurationRepository.getCurrentConfiguration().getProtocol().getName(); 552 553 if (mytimer != null) { 555 mytimer.stop(); 556 } 557 558 switch (mystatus) { 560 561 case Status.STATUS_ACTIVE : 562 case Status.STATUS_MARKED_ROLLBACK : 563 break; 565 566 case Status.STATUS_ROLLEDBACK : 567 TraceTm.jotm.error("ControlImpl.rollback(): already rolled back"); 568 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 569 return; 570 571 default : 572 TraceTm.jotm.error("ControlImpl.rollback(): rollback: bad status"); 573 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 574 completed(false); 575 576 if (protocol == null || !(protocol.equals("iiop"))) { 577 throw new HeuristicMixed("rollback: bad status"); 578 } 579 580 RmiUtility.rethrowRmiException(new TransactionRolledbackException ()); 581 } 582 583 if (!hasSupCoord) { 585 int errors = do_before_completion(); 587 if (errors > 0) { 588 TraceTm.jotm.info("ControlImpl.rollback(): before completion error at rollback"); 589 } 590 } 591 592 try { 594 do_rollback(false); 595 } catch (Exception e) { 596 TraceTm.jotm.error("ControlImpl.rollback(): rollback raised exception ", e); 597 } 598 completed(true); 599 } 600 601 605 611 public synchronized int prepare() throws RemoteException { 612 if (TraceTm.jotm.isDebugEnabled()) { 613 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 614 } 615 616 if (mytimer != null) { 618 mytimer.stop(); 619 } 620 621 switch (mystatus) { 623 624 case Status.STATUS_ACTIVE : 625 break; 627 628 case Status.STATUS_COMMITTED : 629 TraceTm.jotm.error("ControlImpl.prepare(): transaction already commited"); 631 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 632 return Resource.VOTE_COMMIT; 633 634 case Status.STATUS_ROLLEDBACK : 635 TraceTm.jotm.error("ControlImpl.prepare(): transaction already rolled back"); 637 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 638 return Resource.VOTE_ROLLBACK; 639 640 case Status.STATUS_MARKED_ROLLBACK : 641 do_rollback(false); 642 completed(true); 643 return Resource.VOTE_ROLLBACK; 644 645 default : 646 TraceTm.jotm.error("ControlImpl.prepare(): bad status"); 648 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 649 completed(false); 650 return Resource.VOTE_ROLLBACK; 651 } 652 653 int ret = do_prepare(false); 654 655 switch (ret) { 656 case Resource.VOTE_COMMIT : 657 if (TraceTm.jotm.isDebugEnabled()) { 658 TraceTm.jotm.debug("ControlImpl.prepare(): vote commit"); 659 } 660 break; 661 case Resource.VOTE_ROLLBACK : 662 if (TraceTm.jotm.isDebugEnabled()) { 663 TraceTm.jotm.debug("ControlImpl.prepare(): vote rollback"); 664 } 665 do_rollback(false); 666 completed(true); 667 return ret; 668 case Resource.VOTE_READONLY : 669 if (TraceTm.jotm.isDebugEnabled()) { 670 TraceTm.jotm.debug("ControlImpl.prepare(): vote readonly"); 671 } 672 mystatus = Status.STATUS_COMMITTED; 673 completed(true); 674 return ret; 675 } 676 677 680 return ret; 681 } 682 683 687 public synchronized void commit() throws RemoteException { 688 if (TraceTm.jotm.isDebugEnabled()) { 689 TraceTm.jotm.debug("mystatus="+ StatusHelper.getStatusName(mystatus)); 690 } 691 692 switch (mystatus) { 694 case Status.STATUS_PREPARED : 695 break; 697 default : 698 TraceTm.jotm.error("ControlImpl.commit(): commit: bad status"); 700 TraceTm.jotm.error("mystatus= "+ StatusHelper.getStatusName(mystatus)); 701 completed(false); 702 return; 703 } 704 705 if (do_commit(true) == 0) { 707 completed(true); 708 } else { 709 completed(false); 710 } 711 } 712 713 717 public void commit_one_phase() throws RemoteException { 718 if (TraceTm.jotm.isDebugEnabled()) { 719 TraceTm.jotm.debug("ControlImpl.commit_one_phase()"); 720 } 721 722 commit(true); 724 } 725 726 730 public synchronized void forget() throws RemoteException { 731 if (TraceTm.jotm.isDebugEnabled()) { 732 TraceTm.jotm.debug("ControlImpl.forget()"); 733 } 734 735 completed(true); 736 } 737 738 742 747 public int replay_completion(Resource res) throws RemoteException { 748 if (TraceTm.jotm.isDebugEnabled()) { 749 TraceTm.jotm.debug("res="+ res); 750 } 751 return mystatus; 752 } 753 754 758 762 public void timeoutExpired(Object arg) { 763 if (TraceTm.jotm.isDebugEnabled()) { 764 TraceTm.jotm.debug("arg="+ arg); 765 } 766 767 int argvalue = ((Integer ) arg).intValue(); 768 769 switch (argvalue) { 770 case 1 : 771 if (TraceTm.jotm.isDebugEnabled()) { 772 TraceTm.jotm.debug("ControlImpl.timeoutExpired(Object): timeout expired"); 773 } 774 775 try { 776 do_rollback(false); 777 } catch (Exception e) { 778 TraceTm.jotm.error("ControlImpl.timeoutExpired(Object): rollback raised exception ", e); 779 } 780 break; 781 case 2 : 782 if (TraceTm.jotm.isDebugEnabled()) { 783 TraceTm.jotm.debug("ControlImpl.timeoutExpired(Object): removing ControlImpl"); 784 } 785 explicit_destroy(); 786 break; 787 default : 788 TraceTm.jotm.error("ControlImpl.timeoutExpired(Object): timeoutExpired bad value="+ argvalue); 789 break; 790 } 791 } 792 793 797 801 void ding() { 802 if (TraceTm.jotm.isDebugEnabled()) { 803 TraceTm.jotm.debug(""); 804 } 805 } 806 807 815 private int do_prepare(boolean report_heuristics) { 816 if (TraceTm.jotm.isDebugEnabled()) { 817 TraceTm.jotm.debug("report_heuristics="+ report_heuristics); 818 } 819 820 int errors = 0; 821 int ret = Resource.VOTE_READONLY; 822 823 errors = do_before_completion(); 825 826 if (errors > 0) { 827 if (TraceTm.jotm.isDebugEnabled()) { 828 TraceTm.jotm.debug("before_completion failed -> rollback"); 829 } 830 return Resource.VOTE_ROLLBACK; 831 } 832 |