Package com.atomikos.icatch.imp

Source Code of com.atomikos.icatch.imp.TransactionStateHandler

/**
* Copyright (C) 2000-2012 Atomikos <info@atomikos.com>
*
* This code ("Atomikos TransactionsEssentials"), by itself,
* is being distributed under the
* Apache License, Version 2.0 ("License"), a copy of which may be found at
* http://www.atomikos.com/licenses/apache-license-2.0.txt .
* You may not use this file except in compliance with the License.
*
* While the License grants certain patent license rights,
* those patent license rights only extend to the use of
* Atomikos TransactionsEssentials by itself.
*
* This code (Atomikos TransactionsEssentials) contains certain interfaces
* in package (namespace) com.atomikos.icatch
* (including com.atomikos.icatch.Participant) which, if implemented, may
* infringe one or more patents held by Atomikos.
* It should be appreciated that you may NOT implement such interfaces;
* licensing to implement these interfaces must be obtained separately from Atomikos.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/

package com.atomikos.icatch.imp;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Stack;

import com.atomikos.icatch.CompositeTransaction;
import com.atomikos.icatch.Extent;
import com.atomikos.icatch.HeurCommitException;
import com.atomikos.icatch.HeurHazardException;
import com.atomikos.icatch.HeurMixedException;
import com.atomikos.icatch.Participant;
import com.atomikos.icatch.RecoveryCoordinator;
import com.atomikos.icatch.RollbackException;
import com.atomikos.icatch.StringHeuristicMessage;
import com.atomikos.icatch.SubTxAwareParticipant;
import com.atomikos.icatch.Synchronization;
import com.atomikos.icatch.SysException;
import com.atomikos.icatch.TxState;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;

/**
* The state pattern applied to the CompositeTransaction classes.
*/

abstract class TransactionStateHandler implements SubTxAwareParticipant
{
  private static final Logger LOGGER = LoggerFactory.createLogger(TransactionStateHandler.class);

    private int subtxs_;

    private Stack synchronizations_;

    private List subtxawares_;

    private CompositeTransactionImp ct_;

    protected TransactionStateHandler ( CompositeTransactionImp ct )
    {
        ct_ = ct;
        subtxs_ = 0;
        subtxawares_ = new ArrayList ();
        synchronizations_ = new Stack ();
    }

    protected TransactionStateHandler ( CompositeTransactionImp ct ,
            TransactionStateHandler handler )
    {
        subtxs_ = handler.getSubTransactionCount ();
        synchronizations_ = handler.getSynchronizations ();
        subtxawares_ = handler.getSubtxawares ();
        ct_ = ct;

    }
   
    private synchronized void localDecSubTxCount()
    {
      subtxs_--;
    }
   
    private synchronized void localIncSubTxCount()
    {
      subtxs_++;
    }
   
    private synchronized int localGetSubTxCount()
    {
      return subtxs_;
    }
   
    private synchronized void localPushSynchronization ( Synchronization sync )
    {
      synchronizations_.push ( sync );
    }
   
    private synchronized void localAddSubTxAwareParticipant ( SubTxAwareParticipant p )
    {
      subtxawares_.add ( p );
    }

    protected CompositeTransaction createSubTransaction ()
            throws SysException, IllegalStateException
    {
        CompositeTransaction ct = null;
        ct = ct_.getTransactionService ().createSubTransaction ( ct_ );
        // we want to be notified of subtx commit for handling extents
        ct.addSubTxAwareParticipant ( this );
        localIncSubTxCount();
        return ct;
    }

    // this method should NOT be synchronized, to avoid deadlocks in JBoss
    // termination handling at remote servers!
    protected RecoveryCoordinator addParticipant ( Participant participant )
            throws SysException, java.lang.IllegalStateException
    {

        CoordinatorImp coord = ct_.getCoordinatorImp ();
        try {
            coord.addParticipant ( participant );

        } catch ( RollbackException e ) {
            throw new IllegalStateException ( "Transaction already rolled back" );
        }
        return coord;
    }

    protected void registerSynchronization ( Synchronization sync )
            throws IllegalStateException, UnsupportedOperationException, SysException
    {
        if ( sync != null ) {
            try {
                ct_.getCoordinatorImp ().registerSynchronization ( sync );
            } catch ( RollbackException e ) {
                throw new IllegalStateException (
                        "Transaction already rolled back" );
            }
            localPushSynchronization ( sync );
        }
    }

    protected void addSubTxAwareParticipant (
            SubTxAwareParticipant subtxaware ) throws SysException,
            java.lang.IllegalStateException
    {

        localAddSubTxAwareParticipant ( subtxaware );
    }
   
    private void rollback() throws IllegalStateException, SysException
    {
       Stack errors = new Stack ();

         for ( int i = 0; i < subtxawares_.size (); i++ ) {
           SubTxAwareParticipant subtxaware = (SubTxAwareParticipant) subtxawares_.get ( i );
           subtxaware.rolledback ( ct_ );
         }

         Enumeration enumm = null;
         Extent extent = ct_.getExtent ();
         if ( extent != null ) {
           enumm = extent.getParticipants ().elements ();
           while ( enumm.hasMoreElements () ) {
             Participant part = (Participant) enumm.nextElement();
             addParticipant ( part );
           }
         }

         ct_.localSetTransactionStateHandler ( new TxTerminatedStateHandler ( ct_, this, false ) );

         try {
             ct_.getCoordinatorImp().rollback();
         } catch ( HeurCommitException e ) {
             errors.push ( e );
             throw new SysException ( "Unexpected error in rollback", errors );
         } catch ( HeurMixedException e ) {
             errors.push ( e );
             throw new SysException ( "Unexpected error in rollback", errors );
         } catch ( HeurHazardException e ) {
             errors.push ( e );
             throw new SysException ( "Unexpected error in rollback", errors );
         }
    }

    protected void rollbackWithStateCheck () throws java.lang.IllegalStateException,
            SysException
    {
        //prevent concurrent commits - relevant if this is a timeout thread
        ct_.localTestAndSetTransactionStateHandler ( this , new TxTerminatingStateHandler ( false , ct_ , this ) );
        rollback();

    }

    // IMPORTANT: don't synchronize the commit method, because it causes deadlocks
    // (since this method also indirectly locks the coordinator and the FSM)
    // This deadlock happens in particular when application commit interleaves
    // with timeout-driven rollback (during preEnter, the rollback of this same
    // handler is invoked)
    protected void commit () throws SysException,
            java.lang.IllegalStateException, RollbackException
    {
        Stack participants = null;
        Stack synchronizations = null;
       
        //prevent concurrent rollback due to timeout
        ct_.localTestAndSetTransactionStateHandler ( this , new TxTerminatingStateHandler ( true , ct_ , this ) );

        // NOTE: this must be done BEFORE calling notifications
        // to make sure that active recovery works for early prepares
        if ( ct_.isLocalRoot () ) {

          ct_.getCoordinatorImp ().addTag ( ct_.tag_ );

          Enumeration enumm = ct_.getExtent ().getParticipants ().elements ();
          while ( enumm.hasMoreElements () ) {
            Participant part = (Participant) enumm.nextElement ();
            addParticipant ( part );

          }
        }

        if ( subtxs_ > 0 ) throw new IllegalStateException ( "Active subtransactions exist" );

        // BEFORE calling SubTxAwares, make sure that synchronizations
        // are called. This is because the calling thread must still be
        // associated with the tx at beforeCompletion, and the
        // TM is listening as a SubTxAware!
        // NOTE: doing this at the very beginning of commit
        // also makes sure that the tx can still get new Participants
        // from beforeCompletion work being done! This is required.
        Synchronization sync = null;
        Enumeration enumm = synchronizations_.elements ();
        while ( enumm.hasMoreElements () ) {
          sync = (Synchronization) enumm.nextElement ();
          try {
            sync.beforeCompletion ();
          } catch ( RuntimeException error ) {
            // see case 24246: rollback only
            setRollbackOnly();
            LOGGER.logWarning ( "Unexpected error in beforeCompletion: " , error );
          }
        }

        if ( ct_.getState().equals ( TxState.MARKED_ABORT ) ) {
          // happens if synchronization has called setRollbackOnly
          rollback();
          throw new RollbackException ( "The transaction was set to rollback only" );
        }

        // for loop to make sure that new registrations are possible during callback
        for ( int i = 0; i < subtxawares_.size (); i++ ) {
          SubTxAwareParticipant subtxaware = (SubTxAwareParticipant) subtxawares_.get ( i );
          subtxaware.committed ( ct_ );
        }

        ct_.localSetTransactionStateHandler ( new TxTerminatedStateHandler ( ct_, this, true ) );



    }

    protected void setRollbackOnly ()
    {
      ct_.getCoordinatorImp().setRollbackOnly();
        synchronized ( this ) {
          ct_.localSetTransactionStateHandler ( new TxRollbackOnlyStateHandler ( ct_,this ) );
        }

    }

    public void committed ( CompositeTransaction subtx )
    {
        CompositeTransactionImp ct = (CompositeTransactionImp) subtx;
        Extent toAdd = subtx.getTransactionControl().getExtent();
        Extent target = ct_.getExtent();
        target.add ( toAdd );

        SubTransactionCoordinatorParticipant part = new SubTransactionCoordinatorParticipant ( ct.getCoordinatorImp() );
        addParticipant ( part );
     
        localDecSubTxCount();
    }

    public void rolledback ( CompositeTransaction subtx )
    {
        localDecSubTxCount();
    }

    protected abstract Object getState();


    protected List getSubtxawares()
    {
        return subtxawares_;
    }

    protected CompositeTransactionImp getCT()
    {
        return ct_;
    }


    protected int getSubTransactionCount()
    {
        return localGetSubTxCount();
    }

    protected Stack getSynchronizations()
    {
        return synchronizations_;
    }

    protected void addSynchronizations ( Stack synchronizations )
    {
        while ( !synchronizations.empty() ) {
            Synchronization next = (Synchronization) synchronizations.pop();
            localPushSynchronization ( next );
        }
    }

}
TOP

Related Classes of com.atomikos.icatch.imp.TransactionStateHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.