FileDocCategorySizeDatePackage
CurrentImpl.javaAPI DocGlassfish v2 API38120Wed Jun 13 23:03:46 BST 2007com.sun.jts.CosTransactions

CurrentImpl

public class CurrentImpl extends org.omg.CORBA.LocalObject implements org.omg.CosTransactions.Current
The CurrentImpl class is our implementation of the standard Current interface. It provides operations that enable the demarcation of a transaction's scope. These operations are specified in pseudo-IDL. The CurrentImpl ensures that the CurrentTransaction class is set up when the CurrentImpl is created. As an instance of this class may be accessed from multiple threads within a process, serialisation for thread-safety is necessary in the implementation.
version
0.01
author
Simon Holdsworth, IBM Corporation
see

Fields Summary
private int
timeOut
private static boolean
active
private TransactionFactory
factory
static Logger
_logger
Constructors Summary
CurrentImpl()
Default CurrentImpl constructor.

param
return
see


              
     

        // Ensure the CurrentTransaction state has been initialised.

        CurrentTransaction.initialise();
    
Methods Summary
public java.lang.String[]_ids()

        return null;
    
public voidbegin()
Creates a new Control object, containing new Terminator and Coordinator objects.

The current timeout value is passed to the Coordinator.

The Control object is made the current one for the thread on which this method was invoked. If there is already a current Control the existing Control that represents the parent transaction is stacked behind the new one, which becomes the current one.

param
return
exception
SubtransactionsUnavailable A subtransaction cannot be begun, either because the Transaction Service does not support nested transactions or because the current transaction is completing.
exception
INVALID_TRANSACTION The transaction could not be begun as the current thread of control has pending non-transactional work.
exception
SystemException The operation failed.
see


        ControlImpl controlImpl = null;

        // Until we need to check for resync in progress, synchronize the method.

        synchronized(this) {

            // If the transaction service is not active, throw an exception.

            if( !active ) {
                NO_PERMISSION exc = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw exc;
            }

            // Get a reference to the current ControlImpl object.

            try {
                controlImpl = CurrentTransaction.getCurrent();
            } catch( SystemException exc ) {
            }

            // Release the lock now so that if the TransactionFactoryImpl call has to block
            // (during resync), the lock does not prevent other threads from running.

        }

        // If there is a current Control object, then we should try to begin a
        // subtransaction.

        if( controlImpl != null )
            try {

                // Get the Coordinator reference, and use it to create a subtransaction.
                // If an exception was raised, return it to the caller.

                Coordinator coord = controlImpl.get_coordinator();

                // Create a new Control object to represent the subtransaction.

                Control control = coord.create_subtransaction();

                // This control object may be remote, if the original Control object was.
                // In this case we need to deal with it in the same was as we do in the
                // resume method.  Any exception which is thrown during this process will
                // result in SubtransactionsUnavailable thrown to the caller.

                JControl jcontrol = JControlHelper.narrow(control);
                if( jcontrol != null )
                    controlImpl = ControlImpl.servant(jcontrol);

                // If there is no local ControlImpl object for the transaction, we create one
                // now.

                if( controlImpl == null )
                    controlImpl = new ControlImpl(control);
            } catch( Throwable exc ) {
                SubtransactionsUnavailable ex2 = new SubtransactionsUnavailable();
                throw ex2;
            }

        // If there is no current ControlImpl object, create a new top-level transaction

        else {
            //$   CurrentTransaction.report();
            //$   RecoveryManager.report();
            //$   ControlImpl.report();
            //$   CoordinatorLog.report();
            //$   TimeoutManager.report();
            //
            try {

                // Get the TransactionFactory which should be used from this application.
                // This block must be synchronized so that different threads do not try
                // this concurrently.

                synchronized(this) {
                    if( factory == null )
                        factory = Configuration.getFactory();
                }

                // Create the new transaction.

                if (factory != null) {
		    		if(_logger.isLoggable(Level.FINEST))
                    {
						_logger.logp(Level.FINEST,"CurrentImpl","begin()",
								"Before invoking create() on TxFactory");
                    }
 
                    if (Configuration.isLocalFactory()) {
                      controlImpl = ((TransactionFactoryImpl) factory).localCreate(timeOut);
                    } else {
                      Control control = factory.create(timeOut);

                      // This control object is remote.
                      // In this case we need to deal with it in the same was as we do in the
                      // resume method.  Any exception which is thrown during this process will
                      // result in SubtransactionsUnavailable thrown to the caller.

                      JControl jcontrol = JControlHelper.narrow(control);
                      if (jcontrol != null) {
                          controlImpl = ControlImpl.servant(jcontrol);
                      }

                      // If there is no local ControlImpl object for the transaction, we create one
                      // now.

                      if (controlImpl == null) {
                          controlImpl = new ControlImpl(control);
                      }
                    }
                }
            } catch( Throwable exc ) {
				_logger.log(Level.WARNING,
						"jts.unexpected_error_in_begin",exc);
						
            }
        }

        // If the new Control reference is NULL, raise an error at this point.

        if( controlImpl == null ){
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.FactoryFailed,
                                                              CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Make the new Control reference the current one, indicating that the
        // existing one (if any) should be stacked.

        else
            try {
				if(_logger.isLoggable(Level.FINEST))
                    {
						_logger.logp(Level.FINEST,"CurrentImpl","begin()",
								"Before invoking CurrentTransaction.setCurrent(control,true)");
                    }
                CurrentTransaction.setCurrent(controlImpl,true);
            }

        // The INVALID_TRANSACTION exception at this point indicates that the transaction
        // may not be started.  Clean up the state of the objects in the transaction.

        catch( INVALID_TRANSACTION exc ) {
            controlImpl.destroy();
            throw (INVALID_TRANSACTION)exc.fillInStackTrace();
        }

    
public voidbegin(int time_out)
Creates a new Control object, containing new Terminator and Coordinator objects.

Input parameter timeout value is passed to the Coordinator.

The Control object is made the current one for the thread on which this method was invoked. If there is already a current Control the existing Control that represents the parent transaction is stacked behind the new one, which becomes the current one.

param
return
exception
SubtransactionsUnavailable A subtransaction cannot be begun, either because the Transaction Service does not support nested transactions or because the current transaction is completing.
exception
INVALID_TRANSACTION The transaction could not be begun as the current thread of control has pending non-transactional work.
exception
SystemException The operation failed.
see


        ControlImpl controlImpl = null;

        // Until we need to check for resync in progress, synchronize the method.

        synchronized(this) {

            // If the transaction service is not active, throw an exception.

            if( !active ) {
                NO_PERMISSION exc = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw exc;
            }

            // Get a reference to the current ControlImpl object.

            try {
                controlImpl = CurrentTransaction.getCurrent();
            } catch( SystemException exc ) {
            }

            // Release the lock now so that if the TransactionFactoryImpl call has to block
            // (during resync), the lock does not prevent other threads from running.

        }

        // If there is a current Control object, then we should try to begin a
        // subtransaction.

        if( controlImpl != null )
            try {

                // Get the Coordinator reference, and use it to create a subtransaction.
                // If an exception was raised, return it to the caller.

                Coordinator coord = controlImpl.get_coordinator();

                // Create a new Control object to represent the subtransaction.

                Control control = coord.create_subtransaction();

                // This control object may be remote, if the original Control object was.
                // In this case we need to deal with it in the same was as we do in the
                // resume method.  Any exception which is thrown during this process will
                // result in SubtransactionsUnavailable thrown to the caller.

                JControl jcontrol = JControlHelper.narrow(control);
                if( jcontrol != null )
                    controlImpl = ControlImpl.servant(jcontrol);

                // If there is no local ControlImpl object for the transaction, we create one
                // now.

                if( controlImpl == null )
                    controlImpl = new ControlImpl(control);
            } catch( Throwable exc ) {
                SubtransactionsUnavailable ex2 = new SubtransactionsUnavailable();
                throw ex2;
            }

        // If there is no current ControlImpl object, create a new top-level transaction

        else {
            //$   CurrentTransaction.report();
            //$   RecoveryManager.report();
            //$   ControlImpl.report();
            //$   CoordinatorLog.report();
            //$   TimeoutManager.report();
            //
            try {

                // Get the TransactionFactory which should be used from this application.
                // This block must be synchronized so that different threads do not try
                // this concurrently.

                synchronized(this) {
                    if( factory == null )
                        factory = Configuration.getFactory();
                }

                // Create the new transaction.

                if (factory != null) {
		    		if(_logger.isLoggable(Level.FINEST))
                    {
						_logger.logp(Level.FINEST,"CurrentImpl","begin()",
								"Before invoking create() on TxFactory");
                    }
 
                    if (Configuration.isLocalFactory()) {
                      controlImpl = ((TransactionFactoryImpl) factory).localCreate(time_out);
                    } else {
                      Control control = factory.create(time_out);

                      // This control object is remote.
                      // In this case we need to deal with it in the same was as we do in the
                      // resume method.  Any exception which is thrown during this process will
                      // result in SubtransactionsUnavailable thrown to the caller.

                      JControl jcontrol = JControlHelper.narrow(control);
                      if (jcontrol != null) {
                          controlImpl = ControlImpl.servant(jcontrol);
                      }

                      // If there is no local ControlImpl object for the transaction, we create one
                      // now.

                      if (controlImpl == null) {
                          controlImpl = new ControlImpl(control);
                      }
                    }
                }
            } catch( Throwable exc ) {
				_logger.log(Level.WARNING,
						"jts.unexpected_error_in_begin",exc);
						
            }
        }

        // If the new Control reference is NULL, raise an error at this point.

        if( controlImpl == null ){
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.FactoryFailed,
                                                              CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Make the new Control reference the current one, indicating that the
        // existing one (if any) should be stacked.

        else
            try {
				if(_logger.isLoggable(Level.FINEST))
                    {
						_logger.logp(Level.FINEST,"CurrentImpl","begin()",
								"Before invoking CurrentTransaction.setCurrent(control,true)");
                    }
                CurrentTransaction.setCurrent(controlImpl,true);
            }

        // The INVALID_TRANSACTION exception at this point indicates that the transaction
        // may not be started.  Clean up the state of the objects in the transaction.

        catch( INVALID_TRANSACTION exc ) {
            controlImpl.destroy();
            throw (INVALID_TRANSACTION)exc.fillInStackTrace();
        }

    
public voidcommit(boolean reportHeuristics)
Completes the current transaction.

This operation can only be called if there is a Terminator object available.

param
reportHeuristics Indicates that heuristic exceptions should be passed back to the caller.
return
exception
NoTransaction There is no current transaction to commit.
exception
INVALID_TRANSACTION The current transaction has outstanding work and the Transaction Service is "checked".
exception
NO_PERMISSION The caller is not allowed to commit the transaction.
exception
TRANSACTION_ROLLEDBACK The transaction could not be committed, and has been rolled back.
exception
HeuristicHazard Heuristic action may have been taken by a participant in the transaction.
exception
HeuristicMixed Heuristic action has been taken by a participant in the transaction.
exception
SystemException The operation failed.
see


        // Get the current Control object.  If there is none, raise the
        // NoTransaction exception and return.

        ControlImpl controlImpl = CurrentTransaction.getCurrent();
        if( controlImpl == null ) {
            NoTransaction exc = new NoTransaction();
            throw exc;
        }

        // Get the local identifier from the Control object. Raise an exception if
        // the transaction the Control represents has been completed.

        int active = 1;

        if( !controlImpl.representsRemoteControl() ) {

            StatusHolder status = new StatusHolder();
            Long localTID = new Long(controlImpl.getLocalTID(status));

            if( status.value != Status.StatusActive ) {

                // added (Ram J) to handle asynchronous aborts. If a
                // thread calls commit after an asynchronous abort happens,
                // end the thread-tx association before throwing
                // TRANSACTION_ROLLEDBACK exception.
                // In the case where someone had called terminator.commit
                // directly successfully, then end the thread association,
                // before throwing INVALID_TRANSACTION exception.
                CurrentTransaction.endCurrent(true);

                if( status.value == Status.StatusRolledBack ) {
                    TRANSACTION_ROLLEDBACK exc =
                        new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
                    throw exc;
                }

                INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.Completed,
                                                                  CompletionStatus.COMPLETED_NO);
                throw exc;
            }

            // Check whether there are outstanding requests for this transaction, or
            // other active threads.

            active = controlImpl.numAssociated();
        }

        // If this is not the only active thread or there are outstanding requests,
        // raise an exception and return.

        if( (active != 1) || (controlImpl.isOutgoing()) ) {
            if( active != 1 ) {
            }

            if( controlImpl.isOutgoing() ) {
            }

            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.DeferredActivities,
                                                              CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Get the Terminator from the current Control object.  If this fails, then
        // return whatever exception was raised to the caller.

        else {
            Terminator term = null;

            if (Configuration.isLocalFactory()) {
              try {
                term = controlImpl.get_localTerminator();
              } catch (Throwable exc) {
                NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw ex2;
              }
            } else {
              try {
                  term = controlImpl.get_terminator();
              } catch( Throwable exc ) {
                NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw ex2;
              }

              // Tell the Terminator to commit the transaction.
              // This will end the current association of the transaction, if the
              // Terminator is local.  If the Terminator is remote, we end the association
              // ourselves, and do not request unstacking as there will be no stacked
              // Control.

              // End the association if the Terminator is remote.  This is done under a
              // local environment to ignore any exception.  This must be done before
              // the Terminator is called otherwise the ControlImpl object will get
              // confused.

              try {
                if( Configuration.getProxyChecker().isProxy(term) )
                    CurrentTransaction.endCurrent(true);
              } catch( Throwable exc ) {}
            }
            // Commit the transaction.

	    try{
            	term.commit(reportHeuristics);
            } catch (TRANSACTION_ROLLEDBACK e) {
                // ADDED (Ram J) (10/15/01) To handle asynchronous aborts. End
                // thread-tx association before re-throwing exception. This is
                // because commit/rollback operation by a different thread
                // does not set all other thread's control's status to INACTIVE 
                // anymore, for performance purposes.
                CurrentTransaction.endCurrent(true);
                throw e;
            }

            // Free the ControlImpl object.

            controlImpl.destroy();
        }

    
static voiddeactivate()
Prevents any further transactional activity in the process.

param
return
see

        active = false;
    
public Controlget_control()
Returns the current ControlImpl object.

param
return
The Control object for the current transaction, or null if there is no current transaction.
exception
TRANSACTION_ROLLEDBACK The current transaction has been rolled back.
see

        Control result = null;

        // Get the current Control reference from the TransactionManager. If there
        // is none, return a NULL pointer.
        // If the current Control object indicates that the transaction has ended,
        // then the current association will be ended and the TRANSACTION_ROLLEDBACK
        // exception will be raised.

        ControlImpl control = CurrentTransaction.getCurrent();
        if (control != null) {
          if (Configuration.isLocalFactory()) {
            result = (Control) control;
          } else {
            result = control.object();
          }
        }

        return result;
    
public Statusget_status()
Returns the status of the current transaction.

param
return
The current status of the transaction. If there is no current transaction, the value StatusNoTransaction is returned.
see


        Status result = Status.StatusNoTransaction;
        try {
            Coordinator coord = CurrentTransaction.getCurrentCoordinator();

            // Ask the Coordinator object for its status, and return the value.

            if( coord != null )
                result = coord.get_status();
        } catch( Unavailable exc ) {
        } catch( TRANSACTION_ROLLEDBACK exc ) {
            result = Status.StatusRolledBack;
        } catch( SystemException exc ) {
            result = Status.StatusUnknown;
        }

        return result;
    
public intget_timeout()

	return timeOut;
    
public java.lang.Stringget_transaction_name()
Returns a printable string representing the current transaction.

param
return
The transaction name. If there is no current transaction, null is returned.
see


        String result = null;
        try {
            Coordinator coord = CurrentTransaction.getCurrentCoordinator();

            // Ask the Coordinator object for its name, and return the value.

            if( coord != null )
                result = coord.get_transaction_name();
        }

        // Ignore Unavailable (return null in this case), but allow other exceptions
        // to percolate up.

        catch( Unavailable exc ) {}

        return result;
    
public voidresume(Control control)
Re-associates the given Control to the calling thread.

If there is already a current ControlImpl, it is replaced as the current one.

param
control The Control object to be made current.
return
exception
InvalidControl The Control object passed as a parameter is not valid. This may be because the transaction it represents has already completed, or because the object is of the wrong type.
exception
INVALID_TRANSACTION The transaction could not be begun as the current thread of control has pending non-transactional work.
see


        ControlImpl contImpl = null;

        // If the Control object is NULL, then this operation is actually a suspend
        // operation, so end the current association with the thread.

        if( control == null )
            CurrentTransaction.endCurrent(false);
        else {

            if (Configuration.isLocalFactory()) {
                contImpl = (ControlImpl) control;
            } else {
              // Check the ControlImpl object is valid.
              JControl jcontrol = JControlHelper.narrow(control);

              // Try to locate the local ControlImpl object for the transaction.

              if( jcontrol != null )
                contImpl = ControlImpl.servant(jcontrol);

              // If there is no local ControlImpl object for the transaction, we create one
              // now.

              if( contImpl == null )
                try {
                    contImpl = new ControlImpl(control);
                } catch( Exception exc ) {

                    InvalidControl ex2 = new InvalidControl();
                    throw ex2;
                }
             }

            // End the current association regardless of whether there is one.
            // Attempt to make the given ControlImpl object the current one.

            try {
                CurrentTransaction.endCurrent(false);
                CurrentTransaction.setCurrent(contImpl,false);
                if(_logger.isLoggable(Level.FINEST))
                {
					_logger.logp(Level.FINEST,"CurrentImpl","resume(control)",
							"Current thread has been associated with control :"
							+contImpl);
                }
            }

            // The INVALID_TRANSACTION exception at this point indicates that the transaction
            // may not be resumed.

            catch( INVALID_TRANSACTION exc ) {
                throw (INVALID_TRANSACTION)exc.fillInStackTrace();
            }
        }

    
public voidrollback()
Rolls back the changes performed under the current transaction.

This operation can only be called if there is a Terminator object available.

param
return
exception
NoTransaction There is no current transaction to rollback.
exception
INVALID_TRANSACTION The current transaction has outstanding work and the Transaction Service is "checked".
exception
NO_PERMISSION The caller is not allowed to roll the transaction back.
exception
TRANSACTION_ROLLEDBACK The transaction has already been rolled back.
exception
SystemException The operation failed.
see


        ControlImpl controlImpl = CurrentTransaction.getCurrent();

        if( controlImpl == null ) {
            NoTransaction exc = new NoTransaction();
            throw exc;
        }

        // Get the local identifier from the Control object. Raise an exception if
        // the transaction the Control represents has been completed.

        int active = 1;

        if( !controlImpl.representsRemoteControl() ) {

            StatusHolder status = new StatusHolder();
            Long localTID = new Long(controlImpl.getLocalTID(status));

            if( status.value != Status.StatusActive ) {

                // added (Ram J) to handle asynchronous aborts. If a
                // thread calls rollback after an asynchronous abort happens,
                // end the thread-tx association before throwing
                // TRANSACTION_ROLLEDBACK exception.
                // In the case where someone had called terminator.commit
                // directly successfully, then end the thread association,
                // before throwing INVALID_TRANSACTION exception.
                CurrentTransaction.endCurrent(true);

                if( status.value == Status.StatusRolledBack ) {
                    /* TN - do not throw rollback exception
                    TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_NO);
                    throw exc;
                    */
                    return;
                }

                INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.Completed,
                                                                  CompletionStatus.COMPLETED_NO);
                throw exc;
            }

            // Check whether there are outstanding requests for this transaction, or
            // other active threads.

            active = controlImpl.numAssociated();
        }

        // If this is not the only active thread or there are outstanding requests,
        // raise an exception and return.

        if( (active != 1) || (controlImpl.isOutgoing()) ) {
            if( active != 1 ) {
            }

            if( controlImpl.isOutgoing() ) {
            }

            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(MinorCode.DeferredActivities,
                                                              CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Get the Terminator from the current Control object.  If this fails, then
        // return whatever exception was raised to the caller.

        else {
            Terminator term = null;

            if (Configuration.isLocalFactory()) {
              try {
                  term = controlImpl.get_localTerminator();
              } catch( Unavailable exc ) {
                NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw ex2;
              }
            } else {
              try {
                term = controlImpl.get_terminator();
              } catch( Unavailable exc ) {
                NO_PERMISSION ex2 = new NO_PERMISSION(0,CompletionStatus.COMPLETED_NO);
                throw ex2;
              }

              // Tell the Terminator to roll the transaction back.
              // This will end the current association of the transaction, if the
              // Terminator is local.  If the Terminator is remote, we end the association
              // ourselves, and do not request unstacking as there will be no stacked
              // Control.

              // End the association if the Terminator is remote.  This is done under a
              // local environment to ignore any exception.  This must be done before
              // the Terminator is called otherwise the ControlImpl object will get
              // confused.

              try {
                if( Configuration.getProxyChecker().isProxy(term) )
                    CurrentTransaction.endCurrent(true);
              } catch( Throwable exc ) {}
            }
            // Roll the transaction back.

            try{
                term.rollback();
            } catch (TRANSACTION_ROLLEDBACK e) {
                // ADDED (Ram J) (10/15/01) To handle asynchronous aborts. End
                // thread-tx association before re-throwing exception. This is
                // because commit/rollback operation by a different thread
                // does not set all other thread's control's status to INACTIVE 
                // anymore, for performance purposes.
                CurrentTransaction.endCurrent(true);
                //throw e; // no need to throw this for rollback operation.
            }

            // Free the ControlImpl object.

            controlImpl.destroy();
        }

    
public voidrollback_only()
Marks the current transaction such that is cannot be committed and only rolled back.

param
return
exception
NoTransaction There is no current transaction to mark rollback- only.
see


        // Get the reference of the current Coordinator.  If there is none, raise the
        // NoTransaction exception.

        try {
            Coordinator coord = CurrentTransaction.getCurrentCoordinator();

            // Tell the Coordinator to mark itself rollback-only.

            coord.rollback_only();
        } catch( Throwable exc ) {
            throw new NoTransaction();
        }

    
public voidset_timeout(int timeout)
Sets the timeout value to be used for all subsequent transactions.

param
timeout The timeout value in seconds.
return
see

        // timeout < 0 will be rejected (no op).
        // timeout = 0 implies tx has no timeout or a default timeout is used.
        // timeout > 0 implies tx will timeout at the end of the duration.
        if (timeout >= 0) {
            timeOut = timeout;
        }
    
synchronized voidshutdown(boolean immediate)
Shuts down all services.

param
immediate Indicates whether to ignore running transactions.
return
see


        // Inform the basic transaction services to shutdown.

        CurrentTransaction.shutdown(immediate);

    
public Controlsuspend()
Disassociates the current ControlImpl from the calling thread.

param
return
The Control object for the suspended transaction. If there was no transaction, this will be null.
see

        Control result = null;
        ControlImpl cImpl = CurrentTransaction.endCurrent(false);
        if(_logger.isLoggable(Level.FINEST))
        {
			_logger.logp(Level.FINEST,"CurrentImpl","suspend()",
					"Current thread has been disassociated from control :"
					+cImpl);
        }

        if (Configuration.isLocalFactory()) {
            result = (Control) cImpl;
        } else {
          if (cImpl != null) {
            result = cImpl.object();
          }
        }

        return result;