public void end(Xid xid, int flags) throws XAException
   {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "end", new Object[]{xid, flags});
      
      // Are they wanting to suspend the current transaction?
      if ((flags & XAResource.TMSUSPEND) != 0)
      {
         if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "TMSUSPEND was specified");
         
         // Is the resource already in the map? If so, throw an exception
         if (suspendedTransactions.get(xid) != null)
         {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "XID is already suspended");
            
            throw new XAException(XAException.XAER_PROTO);
         }
         
         // Is this XId actually the one currently being used?
         if (currentXid != null && !currentXid.equals(xid))
         {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Attempt to suspend some other XId");
            
            throw new XAException(XAException.XAER_NOTA);
         }
         
         // Add this transaction to the suspended transactions map
         suspendedTransactions.put(xid, currentLiveXAResource);
         currentLiveXAResource.isSuspended = true;
         currentLiveXAResource.setEnlisted(null);
      }
      else
      {
         if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "TMSUSPEND was not specified");
         
         // Is the current XA Resource not active? If so then this is probably a call to
         // simply end a suspended transaction as you can transition to this state without first
         // restarting a suspended transaction.
         if (!currentLiveXAResource.isEnlisted())
         {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Currently not enlisted");
            
            // It is possible that this will be an end call to a suspended transaction (i.e. to skip
            // the restarting). Have a quick check for this XId in our suspended map
            BaseSIXAResourceProxy tx = suspendedTransactions.remove(xid);
            
            // If we find nothing here, then we were not started for this XId and this is a protocol
            // error
            if (tx == null)
            {
               if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "No suspended XId found and not currently started");
               throw new XAException(XAException.XAER_NOTA);
            }
            
            // Restart the suspended transaction
            currentLiveXAResource = tx;
            currentLiveXAResource.setEnlisted(xid);
         }
         
         currentLiveXAResource.isSuspended = false;
         currentLiveXAResource.end(xid, flags);
         
         // Here we can pool the SIXAResource if we have not already done so
         if (!useableXAResources.contains(currentLiveXAResource))
         {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Pooling the SIXAResource");
            useableXAResources.add(currentLiveXAResource);
         }
      }
      
      currentXid = null;
      
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "end");
   }
public void end ( Xid xid , int flags ) throws XAException { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . entry ( this , tc , "end" , new Object [ ] { xid , flags } ) ; if ( ( flags & XAResource . TMSUSPEND ) != 0 ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "TMSUSPEND was specified" ) ; if ( suspendedTransactions . get ( xid ) != null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "XID is already suspended" ) ; throw new XAException ( XAException . XAER_PROTO ) ; } if ( currentXid != null && ! currentXid . equals ( xid ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "Attempt to suspend some other XId" ) ; throw new XAException ( XAException . XAER_NOTA ) ; } suspendedTransactions . put ( xid , currentLiveXAResource ) ; currentLiveXAResource . isSuspended = true ; currentLiveXAResource . setEnlisted ( null ) ; } else { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "TMSUSPEND was not specified" ) ; if ( ! currentLiveXAResource . isEnlisted ( ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "Currently not enlisted" ) ; BaseSIXAResourceProxy tx = suspendedTransactions . remove ( xid ) ; if ( tx == null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "No suspended XId found and not currently started" ) ; throw new XAException ( XAException . XAER_NOTA ) ; } currentLiveXAResource = tx ; currentLiveXAResource . setEnlisted ( xid ) ; } currentLiveXAResource . isSuspended = false ; currentLiveXAResource . end ( xid , flags ) ; if ( ! useableXAResources . contains ( currentLiveXAResource ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "Pooling the SIXAResource" ) ; useableXAResources . add ( currentLiveXAResource ) ; } } currentXid = null ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . exit ( this , tc , "end" ) ; }
The end method is used to signify the end or the temporary end of a unit of work. If the
TMSUSPEND flag is specified, the transaction can be resumed later but other units of work can
be done on the same XAResource during that time.
<p>
If TMSUSPEND is specified the current live XAResource is placed into our suspendedTransactions
map keyed by the XId and a flag is set on the XAResource indicating that it is currently
suspended. This has the effect of informing the start() call that a new XAResource instance is
needed if other units of work are to be started.
<p>
If TMSUSPEND is not specified then either a unit of work is ending normally or a suspended
transaction is being completed. In the event that a suspended transaction is being completed
the associated XAResource is made live (as if they had called start(TMRESUME)) before the
end call is passed onto the real XAResource.

@see javax.transaction.xa.XAResource#end(javax.transaction.xa.Xid, int)