gt:                 Tr.exit(tc, "end", "Exception");
context: /*******************************************************************************
   * Copyright (c) 2003, 2020 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *******************************************************************************/
  
  package com.ibm.adapter.spi;
  
  import javax.transaction.xa.XAException;
  import javax.transaction.xa.XAResource;
  import javax.transaction.xa.Xid;
  
  import com.ibm.adapter.AdapterUtil;
  import com.ibm.ejs.ras.Tr;
  import com.ibm.ejs.ras.TraceComponent;
  import com.ibm.ws.rsadapter.exceptions.TransactionException;
  
  /**
   * Implementation class for XAResource. <p>
   */
  public class XAResourceImpl implements XAResource {
      //private static final TraceComponent tc = Tr.register(XAResourceImpl.class);
      protected static final TraceComponent tc = Tr.register(XAResourceImpl.class); //LIDB2110-69
  
      /** native xa resource */
      private final XAResource ivXaRes;
  
      /** Managed connection */
      private final ManagedConnectionImpl ivMC;
  
      /** State manager */
      private final StateManager ivStateManager;
  
      private static final Class currClass = XAResourceImpl.class;
  
      //This xid is kept because there is a case when end and rollback may be called without an Xid.  This case
      //  is when ManagedConnection.cleanup is called and there is still a connection in a transaction open.
      private Xid ivXid;
  
      //used for XARecovery
      private boolean killJVMBeforeCommit = false;
  
      /**
       * Constructor
       *
       * @param xaRes The XAResource object obtained from the java.sql.Connection
       * @param mc The ManagedConnection instance the sqlConn and XAResource belongs to.
       */
      public XAResourceImpl(XAResource xaRes, ManagedConnectionImpl mc) {
          if (tc.isEntryEnabled())
              Tr.entry(tc, "<init>", new Object[] { xaRes, mc });
  
          ivXaRes = xaRes;
          ivMC = mc;
          ivStateManager = mc.stateMgr;
  
          if (tc.isEntryEnabled())
              Tr.exit(tc, "<init>", this);
      }
  
      /**
       * Commit the global transaction specified by xid.
       * <p>If the resource manager did not commit the transaction and the paramether onePhase is set to true, the
       * resource manager may throw one of the XA_RB* exceptions. Upon return, the resource manager has rolled
       * back the branch's work and has released all held resources.
       *
       * @param Xid A global transaction identifier
       * @param boolean If true, the resource manager should use a one-phase commit protocol to
       *            commit the work done on behalf of xid.
       * @exception XAException - An error has occurred. Possible XAExceptions are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB,
       *                XA_HEURMIX, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
       *                Possible causes for this exception are:
       *                1) the commit call on the actual XAResource failed
       *                2) the commit was called while in an invalid transaction state
       */
  
      @Override
      public void commit(Xid xid, boolean onePhase) throws XAException {
          if (tc.isEntryEnabled())
              Tr.entry(
                       tc,
                       "commit",
                       new Object[] {
                                      this,
                                      ivMC,
                                      xid,
                                      onePhase ? "ONE PHASE" : "TWO PHASE" });
  
          // @alvinso.1
          /*
           * if ( AdapterUtil.getKillServer() )
           * {
           * if (tc.isDebugEnabled())
           * Tr.debug(tc, "Try to kill server process.");
           * AdapterUtil.killServerProcess();
           * }
           */
          //This variable is ONLY used to trigger XARecovery.  Under normal circumstances, of course we want to allow
          //this .commit() method to execute, which in turn will flow the commit to the database and actually commit the transaction.
          //However, in the one single case where we are trying to create a situation in which XARecovery should take place,
          //we set this switch to 'true', which will causes us to do a System.exit() - ie, we simulate
          //a Server crash - and this should result in an 'in-doubt' transaction (because we are assuming that the TransactionManager
          //has already invoked the .end() and .prepare() methods...but we stopped the commit from happening...and end and prepare, with no commit,
          //is the definition of an in-doubt transaction)...which therefore will cause XARecovery to take place when the Server restarts.
          if (killJVMBeforeCommit) {
              System.out.println("The 'killJVMBeforeCommit' switch is set to TRUE.  Doing a System.exit() to kill the server, and generate " +
                                 "an in-doubt transaction that should cause XARecovery to take place.");
              System.exit(1);
          } //end else
          else {
              //The switch is set to false, so allow the commit to happen. Since this is the flow 99.99% of the time, and we go through this
              //code path a ton, we won't clutter up the log with a trace message here.
          } //end else
  
          // LIDB????
          ivMC.isLazyEnlisted = false;
  
          //if (ivMC.isDynamicEnlistment() ) {
          //	// Reset so we can deferred enlist in a future global transaction. [d137506]
          //	ivMC.ivAlreadyProcessedInteractionPendingEvent = false;
          //}
  
          if (ivXid == null) { // d131094
              if (tc.isDebugEnabled())
                  Tr.debug(tc, "XAResource.start was never issued; allowing commit for recovery.");
  
              try {
                  ivStateManager.setState(StateManager.XA_RECOVER);
              } catch (TransactionException te) {
                  if (tc.isDebugEnabled())
                      Tr.debug(
                               tc,
                               "INVALID_TX_STATE",
                               new Object[] {
                                              "XAResource.commit()",
                                              ivMC.getTransactionStateAsString() });
                  XAException xae = new XAException(XAException.XA_HEURCOM);
                  traceXAException(xae, currClass);
  
                  if (tc.isEntryEnabled())
                      Tr.exit(tc, "commit", xae);
                  throw xae;
              }
              ivXid = xid;
          } else if (!xid.equals(ivXid)) { // d129064.1
              if (tc.isDebugEnabled())
                  Tr.debug(
                           tc,
                           "Xid does not match.",
                           new Object[] {
                                          "XAResource.start:  " + ivXid,
                                          "XAResource.commit: " + xid });
  
              XAException xaX = new XAException(XAException.XAER_NOTA);
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "commit", xaX);
              throw xaX;
          }
  
          ivXid = null;
  
          try {
              ivXaRes.commit(xid, onePhase);
              ivStateManager.setState(StateManager.XA_COMMIT);
          } catch (TransactionException te) {
              if (tc.isDebugEnabled())
                  Tr.debug(
                           tc,
                           "INVALID_TX_STATE",
                           new Object[] {
                                          "XAResource.commit()",
                                          ivMC.getTransactionStateAsString() });
              XAException xae = new XAException(XAException.XA_HEURCOM);
              traceXAException(xae, currClass);
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "commit", xae);
              throw xae;
          } catch (XAException xae) {
              traceXAException(xae, currClass);
              //112946
              if (xae.errorCode == XAException.XA_HEURCOM
                  || xae.errorCode == XAException.XA_HEURHAZ
                  || xae.errorCode == XAException.XA_HEURMIX
                  || xae.errorCode == XAException.XA_HEURRB) {
  
                  try {
                      ivXaRes.forget(xid);
                      ivStateManager.setState(StateManager.HEURISTIC_END);
                  } catch (TransactionException te) {
                      if (tc.isDebugEnabled())
                          Tr.debug(
                                   tc,
                                   "DSA_INTERNAL_WARNING",
                                   new Object[] {
                                                  "Exception setting the transaction state to WAS.database=disabled:com.ibm.ws.db2.logwriter=enabledStateManager.HEURISTIC_END from ",
                                                  ivMC.getTransactionStateAsString(),
                                                  te });
                      //should never happen so just eat it
                  } catch (XAException eatXA) {
                      traceXAException(eatXA, currClass);
                      //eat the exception because we are throwing xae instead
                  }
              } //d153590
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "commit", xae);
              throw xae;
          }
  
          if (tc.isEntryEnabled())
              Tr.exit(tc, "commit");
      }
  
      /**
       * Ends the work performed on behalf of a transaction branch. The resource manager
       * disassociates the XA resource from the transaction branch specified and lets the
       * transaction be completed.
       *
       * <p>If TMSUSPEND is specified in flags, the transaction branch is temporarily suspended
       * in incomplete state. The transaction context is in suspened state and must be resumed
       * via start with TMRESUME specified.
       *
       * <p>If TMFAIL is specified, the portion of work has failed. The resource manager may mark
       * the transaction as rollback-only
       *
       * <p>If the end method is called with the TMFAIL flag, the wrappered XAResource is allowed
       * (according to the JTA specification) to throw an XAException with any of the XA_RB* rollback
       * error Codes as part of its normal processing. This does not constitute an error but
       * indicates merely that the RM has marked its branch rollback_only as a result of the TMFAIL.
       *
       * The exception should not be rethrown and should certainly not result in FFDC because
       * the TM will always call rollback after it has called end(TMFAIL).
       *
       * <p>If TMSUCCESS is specified, the portion of work has completed successfully.
       *
       * @param xid Global transaction identifier that must be the same as was used to start the transaction.
       * @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND
       * @exception XAException
       *                An error has occurred. Possible XAException values are XAER_RMERR, XAER_RMFAILED,
       *                XAER_NOTA, XAER_INVAL, XAER_PROTO, or XA_RB*.
       *                Possible causes for this exception are:
       *                <ol>
       *                <li>end call on physical XAResource failed
       *                <li>end was called in an illegal transaction state
       *                </ol>
       */
  
      @Override
      public void end(Xid xid, int flags) throws XAException {
  
          if (tc.isEntryEnabled())
              Tr.entry(
                       tc,
                       "end:MHD",
                       new Object[] {
                                      this,
                                      ivMC,
                                      xid,
                                      AdapterUtil.getXAResourceEndFlagString(flags) });
  
          if (!xid.equals(ivXid)) { // d129064.1
              if (tc.isDebugEnabled())
                  Tr.debug(
                           tc,
                           "Xid does not match.",
                           new Object[] {
                                          "XAResource.start: " + ivXid,
                                          "XAResource.end:   " + xid });
  
              XAException xaX = new XAException(XAException.XAER_NOTA);
              if (tc.isEntryEnabled())
                  Tr.exit(tc, "end", xaX);
              throw xaX;
          }
  
          try {
              //121603 - only set the flag if it is not TMFAIL
              if (flags != XAResource.TMFAIL) {
                  System.out.println("MHD: Setting State to end...");
                  ivStateManager.setState(StateManager.XA_END);
              }
              System.out.println("MHD: Before invoking end...");
              ivXaRes.end(xid, flags);
              System.out.println("MHD: After invoking end...");
  
              // Set the state now if it wasn't set above. [d129064.1]
              if (flags == XAResource.TMFAIL) {
                  System.out.println("MHD: XA-A...");
                  ivStateManager.setState(StateManager.XA_END);
              }
          } //end if
          catch (TransactionException te) {
              //Exception means setState failed because it was invalid to set the state in this case
              System.out.println("MHD: Got this transaction exception....");
              te.printStackTrace();
              if (tc.isDebugEnabled()) {
                  Tr.debug(
                           tc,
                           "INVALID_TX_STATE",
                           new Object[] {
                                          "XAResource.end()",
                                          ivMC.getTransactionStateAsString() });
              } //end if
              try {
                  ivXaRes.rollback(xid);
              } catch (XAException eatXA) {
                  traceXAException(eatXA, currClass);
                  //eat the exception because we will throw the next one
              }
              XAException xae = new XAException(XAException.XA_RBROLLBACK);
              traceXAException(xae, currClass);
              if (tc.isEntryEnabled())
  