FileDocCategorySizeDatePackage
TopCoordinator.javaAPI DocGlassfish v2 API117905Wed Jun 13 23:03:48 BST 2007com.sun.jts.CosTransactions

TopCoordinator

public class TopCoordinator extends CoordinatorImpl
The TopCoordinator interface is our implementation of the standard Coordinator interface that is used for top-level transactions. It allows Resources to be registered for participation in a top-level transaction. In addition the TopCoordinator recovery interface can be used if the connection to a superior Coordinator is lost after a transaction is prepared. As an instance of this class may be accessed from multiple threads within a process, serialisation for thread-safety is necessary in the implementation. The information managed should be reconstructible in the case of a failure.
version
0.02
author
Simon Holdsworth, IBM Corporation
see

Fields Summary
String
name
RegisteredResources
participants
RegisteredSyncs
synchronizations
SuperiorInfo
superInfo
NestingInfo
nestingInfo
TransactionState
tranState
CoordinatorLog
logRecord
CompletionHandler
terminator
boolean
registered
boolean
registeredSync
boolean
root
boolean
rollbackOnly
boolean
dying
boolean
temporary
int
hash
static Logger
_logger
Vector
recoveryCoordinatorList
CoordinatorSynchronizationImpl
coordSyncImpl
boolean
delegated
String
logPath
static String[]
resultName
private static Any
emptyData
Constructors Summary
TopCoordinator()
Default TopCoordinator constructor.

param
return
see


               
     
        // No persistent reference is created in this case.
    
TopCoordinator(int timeOut)
Creates and initialises a new root TopCoordinator, and returns the global identifier for the transaction. The timeout value, if non-zero, is used to establish a time-out for the transaction. A CoordinatorLog object is created at this time if the log is available.

param
timeOut The time-out value for the transaction.
return
exception
LogicErrorException An internal logic error occurred.
see


        // If this execution of the process is recoverable, then create a
        // CoordinatorLog object for the top-level transaction. Each of the
        // implementation classes that use the CoordinatorLog have been written
        // to be able to work with or without a CoordinatorLog reference.

        if (Configuration.isRecoverable()) {
	    // get a CoordinatorLog object from the cache
	    // instead of instantiating a new one    Arun 9/27/99
	    logRecord = CoordinatorLogPool.getCoordinatorLog();
        } else {
            logRecord = null;
        }

        // Allocate a new global identifier for the transaction.

        tranState = new TransactionState(logRecord);

        // Store information about the superior, ancestors and
        // participants of the new transaction.

        superInfo = new SuperiorInfo(tranState.localTID, tranState.globalTID,
                                     null, logRecord);

        // Cache the name  - create a buffer and print the global XID into it.

        // name = superInfo.globalTID.toString();

        // Cache the hash value of the Coordinator.

        hash = superInfo.globalTID.hashCode();

        // Zero out the RegisteredResources, NestingInfo and RegisteredSyncs
        // references. These will be created when they are required.

        nestingInfo = null;
        participants = null;
        synchronizations = null;

        // Set other instance variables.

        root = true;
        registered = true;
        registeredSync = true;
        rollbackOnly = false;
        dying = false;
        temporary = false;
        terminator = null;

        if (!tranState.setState(TransactionState.STATE_ACTIVE)) {

            // Set the state of the transaction to active before making
            // it visible to the TransactionManager.

            LogicErrorException exc =
                new LogicErrorException(
					LogFormatter.getLocalizedMessage(_logger,
					"jts.invalid_state_change"));
            throw exc;

        } else {

            // Inform the RecoveryManager of the existence of this transaction.
            if (!RecoveryManager.addCoordinator(tranState.globalTID,
                                                tranState.localTID,
                                                this,
                                                timeOut)) {
                LogicErrorException exc =
                    new LogicErrorException(
						LogFormatter.getLocalizedMessage(_logger,
						"jts.transaction_id_already_in_use"));
                throw exc;
            }
        }
    
TopCoordinator(int timeOut, GlobalTID globalTID, Coordinator superior, boolean temporary)
Creates and initialises a subordinate TopCoordinator, given the global identifier and superior Coordinator reference, and returns the local identifier for the transaction. The timeout value, if non-zero, is used to establish a time-out for the subordinate transaction. The temporary flag indicates whether the TopCoordinator was created as a temporary ancestor.

param
timeOut The timeout value for the transaction.
param
globalTID The global identifier for the transaction.
param
superior The superior Coordinator.
param
temporary The temporary indicator.
return
exception
LogicErrorException An internal logic error occurred.
see


        // If this execution of the process is recoverable, then create a
        // CoordinatorLog object for the top-level transaction. Each of the
        // implementation classes that use the CoordinatorLog have been written
        // to be able to work with or without a CoordinatorLog reference.

        if (Configuration.isRecoverable()) {
	    // get a CoordinatorLog object from the cache
	    // instead of instantiating a new one    Arun 9/27/99
	    logRecord = CoordinatorLogPool.getCoordinatorLog();
        } else {
            logRecord = null;
        }

        // Allocate a new local identifier for the transaction.
        // If one cannot be allocated, raise an exception as the
        // transaction cannot be started.

        tranState = new TransactionState(globalTID,logRecord);

        // Store information about the superior, ancestors and participants
        // of the new subordinate transaction.

        superInfo = new SuperiorInfo(tranState.localTID, tranState.globalTID,
                                     superior, logRecord);

        // Cache the name  - create a buffer and print the global XID into it.

        // name = superInfo.globalTID.toString();

        // Cache the hash value of the Coordinator.

        hash = superInfo.globalTID.hashCode();

        // Zero out the RegisteredResources, NestingInfo and RegisteredSyncs
        // references. These will be created when they are required.

        nestingInfo = null;
        participants = null;
        synchronizations = null;

        // Set other instance variables.

        root = false;
        registered = false;
        registeredSync = false;
        rollbackOnly = false;
        dying = false;
        this.temporary = temporary;
        terminator = null;

        // Set the state of the transaction to active before making it
        // visible to the RecoveryManager.

        if (!tranState.setState(TransactionState.STATE_ACTIVE)) {
            LogicErrorException exc =
                new LogicErrorException(
					LogFormatter.getLocalizedMessage(_logger,
					"jts.invalid_state_change"));
            throw exc;
        } else {
            if (!RecoveryManager.addCoordinator(globalTID, tranState.localTID,
                                                this, timeOut)) {
                LogicErrorException exc =
                    new LogicErrorException(
						LogFormatter.getLocalizedMessage(_logger,
						"jts.transaction_id_already_in_use"));
                throw exc;
            }
        }
    
Methods Summary
synchronized booleanaddChild(CoordinatorImpl child)
Adds the given Coordinator reference to the set of children of the target TopCoordinator.

param
child The child Coordinator.
return
Indicates success of the operation.
see


        boolean result;

        // Make sure the NestingInfo instance variables is set up
        // before adding the child.

        if (nestingInfo == null) {
            nestingInfo = new NestingInfo();
        }

        result = nestingInfo.addChild(child);

        return result;
    
synchronized voidafterCompletion(Status status)
Informs the TopCoordinator that the transaction has completed. The TopCoordinator informs all Synchronization objects registered with it that the transaction has completed. It does not need to wait for all responses before returning.

param
status Indicates whether the transaction committed or aborted.
return
see


        // If the Coordinator is still active, set it to read only to prevent
        // the Coordinator from actually rolling back when it is destroyed.

        if (tranState.state == TransactionState.STATE_ACTIVE) {
            tranState.setState(TransactionState.STATE_PREPARING);
            tranState.setState(TransactionState.STATE_PREPARED_READONLY);
        }

        // If there are registered Synchronization objects,
        // tell them the transaction has completed.

        if (synchronizations != null) {

            // Tell the RegisteredSyncs to distribute the after completion
            // messages. If an exception occurs, just report it.

            // synchronizations.distributeAfter(get_status());
            synchronizations.distributeAfter(status);
        }

        // At this point, there is nothing left to do, so destroy ourselves
        // before returning.
        boolean aborted = true;
        if (status == Status.StatusCommitted) {
            aborted = false;
        }
        if (!delegated) {
            RecoveryManager.removeCoordinator(superInfo.globalTID,
                                       superInfo.localTID,
                                       aborted);
        } else {
            DelegatedRecoveryManager.removeCoordinator(superInfo.globalTID,
                                       superInfo.localTID,
                                       aborted, logPath);
        }

        // memory leak fix (Ram J) - cleanup the Recovery Coordinator objs.
        if (recoveryCoordinatorList != null) {
            for (int i = 0; i < recoveryCoordinatorList.size(); i++) {
                RecoveryCoordinatorImpl rcImpl = (RecoveryCoordinatorImpl)
                    recoveryCoordinatorList.elementAt(i);
                rcImpl.destroy();
            }
            recoveryCoordinatorList = null;
        }

        // memory leak fix (Ram J)
        // destroy the CoordinatorSynchronization object.
        if (this.coordSyncImpl != null) {
            this.coordSyncImpl.destroy();
        }
        this.synchronizations = null;

        // destroy the coordinator object.
        destroy();
    
synchronized voidbeforeCompletion()
Informs the TopCoordinator that the transaction is about to complete. The TopCoordinator informs all Synchronization objects registered with it that the transaction is about to complete and waits for all of the replies before this operation completes.

param
return
exception
INVALID_TRANSACTION The transaction is not in a state to commit, due to outstanding work.
see


        // First check for active children, before getting too far in.
        // This is only done for the root Coordinator as for any
        // others its too late.

        if (root && nestingInfo != null && nestingInfo.numChildren() != 0) {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                        MinorCode.UnfinishedSubtransactions,
                                        CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If there are registered Synchronization objects, tell them
        // the transaction is about to prepare.

        if (synchronizations != null) {

            // Tell the RegisteredSyncs to distribute the before completion
            // messages. If an exception is raised, then mark the transaction
            // rollback-only.

            if (!synchronizations.distributeBefore()) {
                rollbackOnly = true;
            }
        }
    
voidcleanUpEmpty(CoordinatorImpl parent)
Cleans up an empty Coordinator.

param
parent The parent Coordinator (always null for a TopCoordinator).
return
see


        // Roll the transaction back, ignoring any exceptions.

        try {
            rollback(true);
        } catch( Throwable exc ) {}
    
voidcommit()
Directs the TopCoordinator to commit the transaction. The TopCoordinator directs all registered Resources to commit. If any Resources raise Heuristic exceptions, the information is recorded, and the Resources are directed to forget the transaction before the Coordinator returns a heuristic exception to its caller.

param
return
exception
HeuristicMixed A Resource has taken an heuristic decision which has resulted in part of the transaction being rolled back.
exception
HeuristicHazard Indicates that heuristic decisions may have been taken which have resulted in part of the transaction being rolled back.
exception
NotPrepared The transaction has not been prepared.
see


        // Until we actually distribute prepare flows, synchronize the method.


        synchronized(this) {
			if(_logger.isLoggable(Level.FINE))
        	{
				_logger.logp(Level.FINE,"TopCoordinator","commit()",
						"Within TopCoordinator.commit()"+"GTID is :"+
						superInfo.globalTID.toString());
        	}

            // If the TopCoordinator voted readonly,
            // produce a warning and return.

            if (tranState.state == TransactionState.STATE_PREPARED_READONLY) {
                return;
            }

            // GDH
            // If the TopCoordinator has already completed due to recovery
            // resync thread, return. (Note there is no
            // need to deal with state ROLLED_BACK here as nothing should have
            // caused us to enter that state and subsequently receive a commit.
            // However the opposite cannot be said to be true as presumed abort
            // can cause a rollback to occur when
            // replay_completion is called on a transaction that
            // has gone away already.

            if (tranState.state == TransactionState.STATE_COMMITTED) {
                return;
            }

            // If the TopCoordinator is in the wrong state, return immediately.

            if (!tranState.setState(TransactionState.STATE_COMMITTING)) {
                _logger.log(Level.SEVERE,"jts.transaction_wrong_state","commit");
				 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "commit"});
				 throw  new org.omg.CORBA.INTERNAL(msg);
                //NotPrepared exc = new NotPrepared();
				//Commented out as code is never executed
                //throw exc;
            }

            // Release the lock before proceeding with commit.

        }

        // Commit all participants.  If a fatal error occurs during
        // this method, then the process must be ended with a fatal error.

        Throwable heuristicExc = null;
        if (participants != null) {
            try {
                participants.distributeCommit();
            } catch (Throwable exc) {
                if (exc instanceof HeuristicMixed ||
                        exc instanceof HeuristicHazard) {
                    heuristicExc = exc;
                }

                // ADDED(Ram J) percolate any system exception
                // back to the caller.
                if (exc instanceof INTERNAL) {
                    throw (INTERNAL) exc;
                }
            }
        }

        // The remainder of the method needs to be synchronized.

        synchronized(this) {

            // Record that objects have been told to commit.

            // Set the state

            if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
                _logger.log(Level.SEVERE,"jts.transaction_wrong_state","commit");
				 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "commit"});
				 throw  new org.omg.CORBA.INTERNAL(msg);
            }

            // Clean up the TopCoordinator after a commit. In the case where
            // the TopCoordinator is a root, the CoordinatorTerm object must be
            // informed that the transaction has completed so that if another
            // caller has committed the transaction the object normally
            // responsible for terminating the transaction can take the
            // appropriate action. NOTE: This may DESTROY the TopCoordinator
            // object so NO INSTANCE VARIABLES should be referenced after the
            // call. In the case where the TopCoordinator is a subordinate, the
            // CoordinatorResource object must be informed that the transaction
            // has been completed so that it can handle any subsequent requests
            // for the transaction.

            if (terminator != null) {
                terminator.setCompleted(false, heuristicExc != null);
            }

            /*  commented out (Ram J) for memory leak fix.
            // If there are no registered Synchronization objects,
            // there is nothing left to do, so get the RecoveryManager
            // to forget about us, then self-destruct.

            if (!root && (synchronizations == null ||
                          !synchronizations.involved())
                         ) {
                RecoveryManager.removeCoordinator(superInfo.globalTID,
                                                  superInfo.localTID,
                                                  false);
                destroy();
            }
            */

             // added (Ram J) for memory leak fix
             // if subordinate, send out afterCompletion. This will
             // destroy the CoordinatorSynchronization and coordinator.
             if (!root) {
                afterCompletion(Status.StatusCommitted);
             }


            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON.     */
            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

            // If there was heuristic damage, report it.

            if (heuristicExc != null) {
                if (heuristicExc instanceof HeuristicMixed) {
                    throw (HeuristicMixed) heuristicExc;
                } else {
                    throw (HeuristicHazard) heuristicExc;
                }
            }
        }
    
booleancommitOnePhase()
commitOnePhase

param
none
return
boolean indicating success or whether two phase commit should be tried.
see


        synchronized (this) {

            // First check for active children, before getting too far
            // into the prepare. This is only done for
            // the root Coordinator as for any others it is too  late.

            if (root && nestingInfo != null &&
                    nestingInfo.numChildren() != 0) {
                INVALID_TRANSACTION exc =
                    new INVALID_TRANSACTION(
                        MinorCode.UnfinishedSubtransactions,
                        CompletionStatus.COMPLETED_NO);
                throw exc;
            }


            // If the Coordinator has > 1 resource return smoothly

            if (participants != null && participants.numRegistered() > 1) {
                // GDH COPDEF1
                return false;
            }

            // If the TopCoordinator is in the wrong state, return immediately.

            if (!tranState.
                setState(TransactionState.STATE_COMMITTING_ONE_PHASE)) {
                return false;
            }

            // Check for marked rollback-only, if we are then we can drive
            // the rollback directly from the 2PC process so return false
            // this will cause use to enter prepare (which will do nothing as
            // it checks the same flag
            // thence directly into rollback

            if (rollbackOnly) {
                return false;
            }

            int timeoutType = TimeoutManager.NO_TIMEOUT;

            // In the root, there is no need for an in-doubt timeout,
            // so cancel the timeout so that the transaction is
            // not rolled back. Otherwise set anin-doubt timeout of 60 seconds.

            if (root) {
                TimeoutManager.setTimeout(superInfo.localTID,
                                          TimeoutManager.NO_TIMEOUT,
                                          60);
            }
            else {
                TimeoutManager.setTimeout(superInfo.localTID,
                                          TimeoutManager.IN_DOUBT_TIMEOUT,
                                          60);
            }


            //
            // Contact the resource (note: participants can exist with
            //                             no resourcesafter recovery)
            //

        }  // first synchronised bit ends now to allow possible callbacks.


        if ((participants != null)  && (participants.numRegistered() == 1)) {
            Throwable heuristicExc = null;
            boolean rolled_back = false;
            try {
                participants.commitOnePhase();
            } catch (Throwable exc) {

                if (exc instanceof HeuristicMixed) {
					// IASRI START 4722886
                    // heuristicExc = exc;
					// IASRI END 4722886
                    if (!tranState.setState(
                            TransactionState.
                                STATE_COMMIT_ONE_PHASE_HEURISTIC_MIXED)) {
								_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                                       "COMMIT_ONE_PHASE (1)");
								 String msg = LogFormatter.getLocalizedMessage(_logger,
								 						"jts.transaction_wrong_state",
														new java.lang.Object[]
														{ "COMMIT_ONE_PHASE (1)"});
								  throw  new org.omg.CORBA.INTERNAL(msg);
                    }
					// IASRI START 4722886
					throw (HeuristicMixed)exc;
					// IASRI END 4722886
                } else if (exc instanceof HeuristicHazard) {
					// IASRI START 4722886
                    // heuristicExc = exc;
					// IASRI END 4722886
                    if (!tranState.setState(
                            TransactionState.
                                STATE_COMMIT_ONE_PHASE_HEURISTIC_HAZARD)) {
								_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                                        "COMMIT_ONE_PHASE (2)");
								 String msg = LogFormatter.getLocalizedMessage(_logger,
								 						"jts.transaction_wrong_state",
														new java.lang.Object[]
														{ "COMMIT_ONE_PHASE (2)"});
								  throw  new org.omg.CORBA.INTERNAL(msg);
                    }
					// IASRI START 4722886
					throw (HeuristicHazard)exc;
					// IASRI END 4722886
                } else if (exc instanceof TRANSACTION_ROLLEDBACK) {
                    rolled_back = true;

                    // GDH COPDEF2 Removed code below that changesd state to
                    // COMMIT_ONE_PHASE_ROLLED_BACK this was unnecessary
                    // as setting the rolled_back flag is picked up just below
                    // where the state is changed. Prior to this change we
                    // tried to set the state to COP_RB twice
                    // in a row which is an error.
                } else if (exc instanceof INTERNAL) {
                    // ADDED (Ram J) percolate up any system exception.
                    throw (INTERNAL) exc;
                } // end else if cascade on the exception types

                // (Other exceptions are not passed back
                // by RegisteredResources)

            } // end of catch block for exceptions

            // (GDH COPDEF1 was after if-else block below)

            // Set the final state now
            if (rolled_back) {

                // GDH COPDEF1 Changed state movement to be via COP_RB
                // even though possible to go direct to RB

                // Change state in two steps - this is traced and only the
                // first change would need a forced log write traditionaly
                if (!tranState.setState(
                        TransactionState.
                            STATE_COMMIT_ONE_PHASE_ROLLED_BACK)) {
								_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                                       "COMMIT_ONE_PHASE (4)");
								 String msg = LogFormatter.getLocalizedMessage(_logger,
								 						"jts.transaction_wrong_state",
														new java.lang.Object[]
														{ "COMMIT_ONE_PHASE (4)"});
								  throw  new org.omg.CORBA.INTERNAL(msg);
                    }
                  /**

                if (!tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
					_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                            "COMMIT_ONE_PHASE (5)");
					 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "COMMIT_ONE_PHASE (5)"});
					  throw  new org.omg.CORBA.INTERNAL(msg);
                }
                   **/
            } else { // we commited

                // GDH COPDEF1 Changed state movement to be via COP_OK
                // this is needed by the state tables as the first
                // state change should ideall be a forced log write.

                // We do the state change in two jumps for better trace
                // and to log the fact that a COP_OK represents a successful
                // prepare - only the fist state changed needs a flushed write.
                if (!tranState.setState(TransactionState.
                                            STATE_COMMITTED_ONE_PHASE_OK)) {
					_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                            "COMMIT_ONE_PHASE (6)");
					 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "COMMIT_ONE_PHASE (6)"});
					  throw  new org.omg.CORBA.INTERNAL(msg);
                }
                /**

                // Now set this coord to commited finally.
                if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
					_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                            "COMMIT_ONE_PHASE (7)");
					 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "COMMIT_ONE_PHASE (7)"});
					  throw  new org.omg.CORBA.INTERNAL(msg);
                }
                 **/
            }  // else we did not rollback


            // The remainder of the method needs to be synchronized too!

            synchronized (this) {

                // Clean up the TopCoordinator after a commit. In the case
                // where the  TopCoordinator is a root,
                // the CoordinatorTerm object must be informed that
                // the transaction has completed so that if another
                // caller has committed the transaction the object
                // normally responsible for terminating the
                // transaction can take the appropriate action. NOTE: This may
                // DESTROY the TopCoordinator object so NO INSTANCE VARIABLES
                // should be referenced after the call.
                // In the case where the TopCoordinator is a subordinate, the
                // CoordinatorResource object must be informed that the
                // transaction has been completed so that it can
                // handle any subsequent requests for the
                // transaction.

                if (terminator != null) {
                    terminator.setCompleted(false, heuristicExc != null);
                }

                /* commented out (Ram J) for memory leak fix.
                // If there are no registered Synchronization objects,
                // there is nothing left to do, so get the RecoveryManager
                // to forget about us, then self-destruct.

                if (!root && (synchronizations == null ||
                              !synchronizations.involved())
                             ) {
                    RecoveryManager.removeCoordinator(superInfo.globalTID,
                                                      superInfo.localTID,
                                                      false);
                    destroy();
                }
                */

                // added (Ram J) for memory leak fix
                // if subordinate, send out afterCompletion. This will
                // destroy the CoordinatorSynchronization and coordinator.
                if (!root) {
                    afterCompletion(Status.StatusCommitted);
                }

                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

                // If there was heuristic damage, report it.

                if (heuristicExc != null) {
                    if (heuristicExc instanceof HeuristicMixed) {
                        throw (HeuristicMixed)heuristicExc;
                    } else {
                        throw (HeuristicHazard)heuristicExc;
                    }
                }

                // If the resource rolled back throw TRANSACTION_ROLLEDBACK

                if (rolled_back) {
                    TRANSACTION_ROLLEDBACK exc =
                        new TRANSACTION_ROLLEDBACK(
                            0, CompletionStatus.COMPLETED_YES);
                    throw exc;
                }

            } //end of any synchronised work

            // Otherwise return normally.

            return true;

        } else {
            // GDH COPDEF1
            // No resources at all - just complete state as for commited

            // We do the state change in two jumps for better trace and to
            // log the fact that a COP_OK represents a successful prepare,
            // only the fist state changed needs a flushed write.
            // (Can't turn of NTFS file caching in Java anyway but the
            // intention is in that direction)
            if (!tranState.
                    setState(TransactionState.STATE_COMMITTED_ONE_PHASE_OK)) {
					_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                            "COMMIT_ONE_PHASE (8)");
					 String msg = LogFormatter.getLocalizedMessage(_logger,
				 						"jts.transaction_wrong_state",
										new java.lang.Object[] { "COMMIT_ONE_PHASE (8)"});
					  throw  new org.omg.CORBA.INTERNAL(msg);
            }

            // Now set this coord to commited finally.
            /*
            if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
				_logger.log(Level.SEVERE,"jts.transaction_wrong_state",
                        "COMMIT_ONE_PHASE (9)");
				 String msg = LogFormatter.getLocalizedMessage(_logger,
			 						"jts.transaction_wrong_state",
									new java.lang.Object[] { "COMMIT_ONE_PHASE (9)"});
				  throw  new org.omg.CORBA.INTERNAL(msg);
            }
            */
        } // end of else clause if no resources

        return true;
    
public synchronized Controlcreate_subtransaction()
Creates a subtransaction and returns a Control object that represents the child transaction.

param
return
The Control object for the new child transaction.
exception
Inactive The Coordinator is completing the subtransaction and cannot create a new child.
see


        Control result = null;

        // First check the state of the transaction. If it is not active,
        // do not allow the subtransaction to be created.

        if (tranState == null ||
                tranState.state != TransactionState.STATE_ACTIVE) {
            Inactive exc = new Inactive();
            throw exc;
        }

        // Set up the sequence of ancestors to hold the single reference
        // and global identifier of the top-level
        // TopCoordinator as there are no ancestors.
        // We do not need to make a copy of the global TID as this is done
        // by the factory when it creates the child.

        CoordinatorImpl[] ancestors = new CoordinatorImpl[1];
        ancestors[0] = this;

        // Create a new SubCoordinator, and initialise it with the given
        // identifiers and ancestry.  If the operation fails,
        // return a NULL Control object, and
        // the SubtransactionsUnavailable exception. Note that the
        // ancestor sequence is not copied by the creation operation.

        SubCoordinator child = null;
        TerminatorImpl terminator = null;
        try {
            child = new SubCoordinator(superInfo.globalTID,
                                       superInfo.localTID,
                                       ancestors);

            // Create a Terminator object, and initialise it with the
            // SubCoordinator reference and a flag to indicate that it
            // represents a subtransaction.

            terminator = new TerminatorImpl(child,true);

            // Create a Control object, and initialise it with the Terminator,
            // SubCoordinator and global OMGtid.

            result = new ControlImpl(terminator, child,
                                     new GlobalTID(child.getGlobalTID()),
                                     new Long(child.getLocalTID())
                                    ).object();
        } catch (Throwable exc) {
            Inactive ex2 = new Inactive();
            throw ex2;
        }

        // If the operation succeeded, add the new child to the set
        // of children. Ensure that the NestingInfo object is set up.

        if (nestingInfo == null) {
            nestingInfo = new NestingInfo();
        }

        nestingInfo.addChild(child);

        return result;
    
synchronized voiddelegated_reconstruct(CoordinatorLog log, java.lang.String logPath)
Directs the TopCoordinator to recover its state after a failure, based on the given CoordinatorLog object for the given logpath. If the TopCoordinator has already been defined or recovered, the operation returns immediately. Otherwise the TopCoordinator restores the state of its internal objects using their recovery operations, which in turn recover their state from the CoordinatorLog object.

param
log The CoordinatorLog object which contains the Coordinators state.
param
logPath Location of the log file
return
see


        // Set up instance variables.

        rollbackOnly = false;
        registered = false;
        registeredSync = false;
        root = false;
        dying = false;
        temporary = false;
        terminator = null;
        logRecord = log;
        name = null;

        // Zero out NestingInfo and Synchronizations references. These won't be
        // needed for a recovered transaction.

        nestingInfo = null;
        synchronizations = null;

        delegated = true;
        this.logPath = logPath;

        // Use the result of the TransactionState reconstruction to
        // decide whether to continue with recovery of this transaction.

        tranState = new TransactionState();
        // int state = tranState.delegated_reconstruct(log);
        int state = tranState.reconstruct(log);
        if (state == TransactionState.STATE_NONE ||
                state == TransactionState.STATE_COMMITTED ||
                // state == TransactionState.STATE_COMMITTED_ONE_PHASE_OK ||
                // state == TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK ||
                state == TransactionState.STATE_ROLLED_BACK) {

            // If the transaction is discarded, then ensure that
            // the log record is discarded.

            CoordinatorLog.removeLog(log.localTID, logPath);
            destroy();

        } else {

            // Otherwise continue with reconstruction.
            participants = new RegisteredResources(this);
            participants.reconstruct(log);

            // Reconstruct the SuperiorInfo object.  This will result in a
            // call to RecoveryManager.addCoordinator (which is done
            // because reconstruction of the object references in the
            // SuperiorInfo requires the Coordinator to
            // already be known to the RecoveryManager).

            superInfo = new SuperiorInfo();
            superInfo.delegated_reconstruct(log, this, logPath);

            // Cache the name  - create a buffer and print the
            // global XID into it.

            name = superInfo.globalTID.toString();

            // Cache the hash value of the Coordinator.

            hash = superInfo.globalTID.hashCode();
        }
    
voiddirectRegisterResource(Resource res)
Registers the given Resource object with the Coordinator with no regard for the state of the transaction or registration with the superior.

This is intended to be used during recovery to enable XA Resource Managers to participate in resync without needing the XA Resource objects to have persistent references.

The Resource object parameter should only refer to a local object.

param
res The Resource to be directly registered.
return
see


        // If the set has not already been created, create it now.
        // Note that we do notpass the CoordinatorLog object to the
        // RegisteredResources as we do not want to do anything
        // with it here.  Generally participants will not be null
        // as this method will be called diring recovery.

        if (participants == null) {
            participants = new RegisteredResources(null, this);
        }

        // Add the reference to the set.  The reference is not duplicated,
        // as this operation should only be called for local Resource objects.

        participants.addRes(res);
		if(_logger.isLoggable(Level.FINE))
        {
			_logger.logp(Level.FINE,"TopCoordinator","directRegisterResource()",
					"Registered resource :" + res );
        }

    
public synchronized voiddoFinalize()
Cleans up the objects state.

param
return
see


        // Set the flag to indicate that the coordinator is being destroyed.

        dying = true;

        // What we do when destroyed depends on the transaction's state.
        // We assume that temporary Coordinators have rolled bak at this point.

        int state = TransactionState.STATE_ROLLED_BACK;
        if (tranState != null && !temporary) {
            state = tranState.state;
        }

        switch (state) {

        // If the transaction is active it should be rolled back.  This
        // will result in the TopCoordinator self-destructing at the
        // end of two-phase commit.

        case TransactionState.STATE_ACTIVE :
            try {
                rollback(true);
            } catch (Throwable exc) {}

            break;

        // For committed or rolled-back, we really need to destroy the
        // object. Also for prepared_readonly.

        case TransactionState.STATE_PREPARED_READONLY :
        case TransactionState.STATE_COMMITTED :
        case TransactionState.STATE_ROLLED_BACK :
        case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
        case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :

	    /*
            if (tranState != null) {
                tranState.finalize();
            }
	    */

            if (superInfo != null) {
                superInfo.doFinalize();
            }

	    /*
            if (nestingInfo != null) {
                nestingInfo.doFinalize();
            }

            if (participants != null) {
                participants.finalize();
            }

            if (synchronizations != null) {
                synchronizations.finalize();
            }
	    */

            tranState = null;
            superInfo = null;
            nestingInfo = null;
            participants = null;
            synchronizations = null;
            logRecord = null;
            terminator = null;
            name = null;
            break;

        // For any other state, the transaction is completing, so the
        // TopCoordinator will eventually self-destruct.  We do nothing here.

        default :
            break;
        }
    
public booleanequals(java.lang.Object other)
Determines equality of the object with the parameter.

param
other The other object.
return
Indicates equality.
see


        // Do a quick check on the object references.

        if( this == other ) return true;

        // Obtain the global identifier for the other Coordinator.

        otid_t otherTID = null;

        // For local Coordinator objects which are really instances of the
        // CoordinatorImpl class, get the global TID via a private method call.

        if (other instanceof CoordinatorImpl) {
            if (other instanceof TopCoordinator) {
                otherTID = ((TopCoordinator) other).
                                superInfo.globalTID.realTID;
            }
        } else if (other instanceof org.omg.CORBA.Object) {

            // For remote Coordinator objects which are instances of
            // the JCoordinator class, use the getGlobalTID method remotely.

            try {
                JCoordinator jcoord = JCoordinatorHelper.
                                        narrow((org.omg.CORBA.Object) other);
                otherTID = jcoord.getGlobalTID();
            } catch (BAD_PARAM exc) {

                // For remote Coordinator objects which are not
                // instances of the JCoordinator class, use the propagation
                // context to compare the Coordinators. This relies on the
                // availability of the propagation
                // context from the target Coordinator.

                try {
                    Coordinator coord =
                        CoordinatorHelper.narrow((org.omg.CORBA.Object) other);
                    PropagationContext pc = coord.get_txcontext();
                    otherTID = pc.current.otid;
                } catch (BAD_PARAM ex2) {
                    // If the other object is not actually a Coordinator,
                    // then the objects are not the same.
                } catch (Unavailable ex2) {
                    // If the other Coordinator is inactive, then there is
                    // nothing we can do to get the global identifier for the
                    // transaction, so we cannot compare the
                    // Coordinator objects.
                    INVALID_TRANSACTION ex3 = new INVALID_TRANSACTION(
                                                MinorCode.CompareFailed,
                                                CompletionStatus.COMPLETED_NO);
                    throw ex3;
                }
            }
        }

        // Compare the global identifiers.

        if (otherTID != null) {
            return superInfo.globalTID.equals(otherTID);
        }

        return false;
    
public synchronized TransIdentity[]getAncestors()
Returns the sequence of ancestors of the transaction.

param
return
The sequence of ancestors.
see

        return null;
    
public otid_tgetGlobalTID()
Returns a global identifier that represents the TopCoordinator's transaction.

This operation references only the global identifier, and so can be implemented locally in a proxy class.

This method is currently not synchronized because that causes a deadlock in resync. I don't think this is a problem as the global identifier is allocated in the constructor and then never changes.

param
return
The global transaction identifier.
see


        otid_t result = superInfo.globalTID.realTID;
        return result;
    
public GlobalTIDgetGlobalTid()

        return superInfo.globalTID;
    
public longgetLocalTID()
Returns the internal identifier for the transaction. This method is currently not synchronized because that causes a deadlock in resync.

param
return
The local identifier.
see


        long result = superInfo.localTID.longValue();
        return result;
    
CoordinatorgetParent()
Gets the parent coordinator of the transaction. As this is a top level coordinator, a parent does not exist so NULL is returned.

param
return
The parent Coordinator, null.
see


        Coordinator result = null;
        return result;
    
public intgetParticipantCount()

        if (participants == null) {
            return 0;
        }
        return participants.numRegistered();
    
CoordinatorgetSuperior()
Gets the superior Coordinator for this transaction.

param
return
The superior Coordinator
see


        Coordinator result = superInfo.superior;
        return result;
    
CompletionHandlergetTerminator()
Gets the object normally responsible for terminating this Coordinator.

param
return
The object normally responsible for terminating the Coordinator.
see


        CompletionHandler result = terminator;
        return result;
    
public Statusget_parent_status()
Gets the local state of the transaction. For a top-level transaction this operation is equivalent to the get_status method. This operation references no instance variables and so can be implemented locally in the proxy class.

param
return
The status of the transaction.
see

        Status result = get_status();
        return result;
    
public Statusget_status()
Returns the local status of the target transaction.

param
return
The status of the transaction.
see


        Status result = Status.StatusUnknown;

        if (tranState != null) {

            switch (tranState.state) {

            // If active, return active or marked rollback-only
            // if the flag is set.

            case TransactionState.STATE_ACTIVE :
                if( rollbackOnly )
                    result = Status.StatusMarkedRollback;
                else
                    result = Status.StatusActive;
                break;

            // If prepared, (successfully or otherwise), return prepared.
            // If committing return prepared (may want to block in this case).

            case TransactionState.STATE_PREPARED_SUCCESS :
            case TransactionState.STATE_PREPARED_FAIL :
            case TransactionState.STATE_PREPARED_READONLY :
                result = Status.StatusPrepared;
                break;

            // If we have no internal state, return that fact.
            // All of these states map directly to the OMG values.

            case TransactionState.STATE_NONE :
                result = Status.StatusNoTransaction;
                break;
            case TransactionState.STATE_PREPARING :
            case TransactionState.STATE_COMMITTING_ONE_PHASE :
                result = Status.StatusPreparing;
                break;
            case TransactionState.STATE_COMMITTING :
                result = Status.StatusCommitting;
                break;
            case TransactionState.STATE_COMMITTED :
            case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
            case TransactionState.STATE_COMMIT_ONE_PHASE_HEURISTIC_HAZARD :
            case TransactionState.STATE_COMMIT_ONE_PHASE_HEURISTIC_MIXED :
                result = Status.StatusCommitted;
                break;
            case TransactionState.STATE_ROLLING_BACK :
            case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :
                result = Status.StatusRollingBack;
                break;
            case TransactionState.STATE_ROLLED_BACK :
                result = Status.StatusRolledBack;
                break;

            // Any other state, return unknown.
            // GDH Including c-o-p heuristic states

            default :
                result = Status.StatusUnknown;
                break;
            }
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
          throw exc;
        }

        return result;
    
public Statusget_top_level_status()
Gets the local state of the transaction. For a top-level transaction this operation is equivalent to the get_status method. This operation references no instance variables and so can be implemented locally in a proxy class.

param
return
The status of the transaction.
see


        Status result = get_status();
        return result;
    
public java.lang.Stringget_transaction_name()
removed synchronization at method level since only tranState requires locking


        String result = null;
        if (tranState != null) {
            if (name == null)
                name = superInfo.globalTID.toString();
            result = new String(name);
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    
public synchronized PropagationContextget_txcontext()
Creates a PropagationContext which contains the information which would normally be passed implicitly via the CosTSPropagation interfaces.

param
return
The transaction context.
exception
Inactive The Coordinator is in the process of completing the transaction and cannot return the information.
see


                                                     
          

        // First check the state of the transaction. If it is not active,
        // do not allow the registration.

        if (tranState == null ||
                tranState.state != TransactionState.STATE_ACTIVE ||
                rollbackOnly ) {
            Unavailable exc = new Unavailable();
            throw exc;
        }

        // Work out the timeout value to pass, if any.
        // Note that only top-level transactions have timeouts.
        // We do not check for timeouts if the Coordinator is remote.
        // If the Coordinator does not have a timeout defined, the
        // TimeoutManager will return a negative value.
        // If the transaction has timed out, the value will be  zero.

        long timeLeft = TimeoutManager.timeLeft(superInfo.localTID);
        int timeout = 0;
        if (timeLeft > 0) {

            timeout = (int)timeLeft/1000;

        } else if (timeLeft == 0) {

            // If the timeout has expired, then do not return a context,
            // but roll the transaction back and
            // throw the TRANSACTION_ROLLEDBACK exception.

            TimeoutManager.timeoutCoordinator(superInfo.localTID,
                                              TimeoutManager.ACTIVE_TIMEOUT);
            TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(
                                            0, CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // Fill in the context with the current transaction information,
        // and the ancestor information.

        TransIdentity current = new TransIdentity(this.object(),
                                                  null,
                                                  superInfo.globalTID.realTID);

        // Ensure that the implementation specific data is filled with a value.

        if (emptyData == null){
            emptyData = Configuration.getORB().create_any();
            emptyData.insert_boolean(false);
        }

        PropagationContext result = new PropagationContext(
                                            timeout, current,
                                            new TransIdentity[0], emptyData);
		if(_logger.isLoggable(Level.FINEST))
        {
			_logger.logp(Level.FINEST,"TopCoordinator","get_txcontext()", 
					"Obtained PropagationContext"+"GTID is: "+
					superInfo.globalTID.toString());
        }

        return result;
    
synchronized booleanhasRegistered()
Checks whether the TopCoordinator has registered with its superior.

param
return
Indicates the registration status.
see


        boolean result = registered || registeredSync;
        return result;
    
public inthashCode()
Returns a hash code for the object.

This very basic method is used by the trace facility and should not call any method which is traced.

param
return
The hash code for the object.
see

        if (hash == 0 && superInfo != null && superInfo.globalTID != null) {
            hash = superInfo.globalTID.hashCode();
        }

        return hash;
    
public synchronized inthash_top_level_tran()
Returns a hash value based on the top-level ancestor of the transaction associated with the target object. This operation references only the global TID, and so can be implemented locally in a proxy class.

param
return
The hash value for the transaction.
see


        int result = hash;

        if (tranState == null) {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);

            throw exc;
        }

        return result;
    
public inthash_transaction()
removed synchronization at method level since only tranState requires locking


        int result = hash;

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

        return result;
    
synchronized booleanisActive()
Checks whether the TopCoordinator is active.

param
return
Indicates the transaction is active.
see


        boolean result = (tranState.state == TransactionState.STATE_ACTIVE);
        return result;
    
public synchronized booleanisRollbackOnly()
Checks whether the TopCoordinator is marked rollback-only.

param
return
Indicates whether the transaction is rollback-only.
see


        boolean result = rollbackOnly;
        return result;
    
public booleanis_ancestor_transaction(Coordinator other)
Determines whether the target TopCoordinator is an ancestor of the given Coordinator. For a top-level transaction returns TRUE if and only if the transaction associated with the target object is an ancestor of the transaction associated with the parameter object. This operation references no instance variables and so can be implemented locally in a proxy class.

param
other The other Coordinator.
return
Indicates the relationship.
exception
SystemException The other Coordinator could not be reached.
see


        boolean result = false;
        if (tranState != null) {
          result = other.is_descendant_transaction(this.object());
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    
public booleanis_descendant_transaction(Coordinator other)
Determines whether the target TopCoordinator is a descendant of the given Coordinator. For a top-level transaction returns TRUE if and only if the transaction associated with the target object is the same as the transaction associated with the parameter object. This operation references no instance variables and so can be implemented locally in a proxy class.

param
other The other Coordinator.
return
Indicates the relationship.
exception
SystemException The other Coordinator could not be reached.
see


        boolean result = false;
        if (tranState != null) {
            result = is_same_transaction(other);
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    
public booleanis_related_transaction(Coordinator other)
Determines whether the target TopCoordinator is related to the given Coordinator (i.e. is a member of the same transaction family). For a top-level transaction returns TRUE if and only if the transaction associated with the parameter object is a descendant of the transaction associated with the target object. This operation references no instance variables and so can be implemented locally in a proxy class.

param
other The other Coordinator.
return
Indicates the relationship.
exception
SystemException The other Coordinator could not be reached.
see


        boolean result = false;

        if (tranState != null) {
            result = other.is_descendant_transaction(this.object());
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    
public booleanis_root_transaction()
Determines whether this TopCoordinator is the root TopCoordinator. the given Coordinator (i.e. is a member of the same transaction family). For a root transaction, this method returns TRUE. Otherwise it returns FALSE.

return
Indicates if this is the root TopCoordinator.
see


        boolean result = root;

        return result;
    
public booleanis_same_transaction(Coordinator other)
removed synchronization at method level since only tranState requires locking


        boolean result = false;

        // Get the names of the two transactions and compare them.

        if (tranState != null) {
            if (name == null)
                name = superInfo.globalTID.toString();
            result = name.equals(other.get_transaction_name());
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                                            MinorCode.Completed,
                                            CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    
public booleanis_top_level_transaction()
Determines whether the target TopCoordinator represents a top-level (non-nested) transaction.

For a top-level transaction returns TRUE.

This operation references no instance variables and so can be implemented locally in a proxy class.

param
return
Indicates this is a top-level transaction.
see


        boolean result = true;
        return result;
    
Voteprepare()
Directs the TopCoordinator to prepare to commit. The TopCoordinator directs all registered Resources to prepare, and returns the result to the caller. The TopCoordinator must guarantee that each Resource object registered with it receives at most one prepare request (This includes the case where the Recoverable Server registers the same Resource twice).

param
return
The consolidated vote.
exception
INVALID_TRANSACTION The transaction is not in a state to commit, due to outstanding work.
exception
HeuristicMixed Indicates that a participant voted to roll the transaction back, but one or more others have already heuristically committed.
exception
HeuristicHazard Indicates that a participant voted to roll the transaction back, but one or more others may have already heuristically committed.
see


                                                                                                                                           
     
                

        Vote result = Vote.VoteRollback;

        // Until we actually distribute prepare flows, synchronize the method.

        synchronized(this) {

            // First check for active children, before getting too far into
            // the prepare. This is only done for the root Coordinator as for
            // any others it is too late.

            if (root && nestingInfo != null &&
                    nestingInfo.numChildren() != 0) {
                INVALID_TRANSACTION exc =
                    new INVALID_TRANSACTION(
                        MinorCode.UnfinishedSubtransactions,
                        CompletionStatus.COMPLETED_NO);
                throw exc;
            }

            // If the TopCoordinator is in the wrong state, return immediately.

            if (!tranState.setState(TransactionState.STATE_PREPARING)) {
                return Vote.VoteRollback;
            }

            // Check for marked rollback-only.

            if (rollbackOnly) {

                // Try to set the state to prepared fail.

                if (!tranState.
                        setState(TransactionState.STATE_PREPARED_FAIL)) {
                    // empty
                }

                return Vote.VoteRollback;
            }

            // Release the lock prior to distributing the prepare operations.
            // This is to allow the transaction to be marked rollback-only
            // (by resources)

        }  // synchronised bit

        // Get the RegisteredResources to distribute prepare operations.
        // If a heuristic exception is thrown, then set the state
        // to rolled back.

        Vote overallResult = Vote.VoteReadOnly;
        Throwable heuristicExc = null;

        if (participants != null) {

            try {

                overallResult = participants.distributePrepare();

		if (overallResult == Vote.VoteCommit || 
				overallResult == Vote.VoteReadOnly) {
		    
		    if (participants.getLAOResource() != null) {
	                if (logRecord == null && Configuration.isDBLoggingEnabled()) {
                            if (!(LogDBHelper.getInstance().addRecord(
				  tranState.localTID.longValue(),
                                  tranState.globalTID.toTidBytes()))) {
                                overallResult = Vote.VoteRollback;
                            }
			}	
			if (overallResult != Vote.VoteRollback) {
                            participants.getLAOResource().commit();
		        }
		    }
		}
            } catch (Throwable exc) {

                // If a heuristic exception was thrown, change the state of
                // the Coordinator to rolled back and clean up before throwing
                // the exception to the caller.

                if (exc instanceof HeuristicMixed ||
                        exc instanceof HeuristicHazard) {

                    if (!tranState.
                            setState(TransactionState.STATE_ROLLED_BACK)) {
                        // empty
                    }

                    /* comented out (Ram J) for memory leak fix.
                    // Discard the Coordinator if there is no after completion.
                    // Root Coordinators and those with registered
                    // Synchronization objects always have after completion
                    // flows. Otherwise remove the RecoveryManager associations
                    // and destroy the Coordinator.

                    if (!root &&
                            (synchronizations == null ||
                             !synchronizations.involved())
                            ) {
                        RecoveryManager.removeCoordinator(superInfo.globalTID,
                                                          superInfo.localTID,
                                                          false);
                        destroy();
                    }
                    */

                    // added (Ram J) for memory leak fix
                    // if subordinate, send out afterCompletion. This will
                    // destroy the CoordinatorSynchronization and coordinator.
                    if (!root) {
                        afterCompletion(Status.StatusRolledBack);
                    }

                    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
                    /* NO INSTANCE VARIABLES MAY BE                      */
                    /*                       ACCESSED FROM THIS POINT ON.*/
                    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

                    if (heuristicExc instanceof HeuristicMixed) {
                        throw (HeuristicMixed)heuristicExc;
                    } else {
                        throw (HeuristicHazard)heuristicExc;
                    }
                }

                // For any other exception, change the vote to rollback

                overallResult = Vote.VoteRollback;

            }  // catch for except

        } // if block

        // The remainder of the method needs to be synchronized.

        synchronized(this) {

            // If the transaction has been marked rollback-only during
            // this process, change the vote.

            if (rollbackOnly) {
                overallResult = Vote.VoteRollback;
            }


            // Set the state depending on the result of the prepare operation.
            // For read-only, we can throw away the Coordinator if there are no
            // synchronization objects, otherwise the Coordinator will
            // be destroyed after synchronization.
            // Set the state to prepared, read-only.

            if (overallResult == Vote.VoteReadOnly) {

                if (!tranState.
                        setState(TransactionState.STATE_PREPARED_READONLY)) {
                    overallResult = Vote.VoteRollback;
                }

                /* commented out (Ram J) for memory leak fix.
                // When voting readonly, discard the Coordinator if there is
                // no after completion. Root Coordinators and those with
                // registered Synchronization objects always have after
                // completion flows. Otherwise remove the
                // RecoveryManager associations and destroy the Coordinator.

                if (!root &&
                        (synchronizations == null ||
                         !synchronizations.involved())
                        ) {
                    RecoveryManager.removeCoordinator(superInfo.globalTID,
                                                      superInfo.localTID,
                                                      false);
                    destroy();
                }
                */

                // added (Ram J) for memory leak fix
                // if subordinate, send out afterCompletion. This will
                // destroy the CoordinatorSynchronization and coordinator.
                // Note: the after_completion status is "unknown", since
                // at this point we do not know if the tx completed sucessfully,
                // as the sync objects are being called before the root
                // actually completes.
                if (!root) {
                    afterCompletion(Status.StatusUnknown);
                }
            } else if (overallResult == Vote.VoteCommit) {

                // For commit, change any active timeout and change the state.

                int timeoutType = TimeoutManager.NO_TIMEOUT;

                // In the root, there is no need for an in-doubt timeout,
                // so cancel the timeout so that the transaction is
                // not rolled back.  Otherwise set an
                // in-doubt timeout of 60 seconds.

                if (!root) {
                    timeoutType = TimeoutManager.IN_DOUBT_TIMEOUT;
                }

                TimeoutManager.setTimeout(superInfo.localTID, timeoutType, 60);

                // Set the state to prepared_success.

                if (!tranState.
                        setState(TransactionState.STATE_PREPARED_SUCCESS)) {
                    overallResult = Vote.VoteRollback;
                }
            } else {

                // By default, assume rollback.  We do not need to cancel
                // the timeout as it  does not matter
                // if the transaction is subsequently rolled back.

                if (!tranState.
                        setState(TransactionState.STATE_PREPARED_FAIL)) {
                    overallResult = Vote.VoteRollback;
                }
            }
        }

        return overallResult;
    
synchronized voidreconstruct(CoordinatorLog log)
Directs the TopCoordinator to recover its state after a failure, based on the given CoordinatorLog object. If the TopCoordinator has already been defined or recovered, the operation returns immediately. Otherwise the TopCoordinator restores the state of its internal objects using their recovery operations, which in turn recover their state from the CoordinatorLog object.

param
log The CoordinatorLog object which contains the Coordinators state.
return
see


        // Set up instance variables.

        rollbackOnly = false;
        registered = false;
        registeredSync = false;
        root = false;
        dying = false;
        temporary = false;
        terminator = null;
        logRecord = log;
        name = null;

        // Zero out NestingInfo and Synchronizations references. These won't be
        // needed for a recovered transaction.

        nestingInfo = null;
        synchronizations = null;

        // Use the result of the TransactionState reconstruction to
        // decide whether to continue with recovery of this transaction.

        tranState = new TransactionState();
        int state = tranState.reconstruct(log);
        if (state == TransactionState.STATE_NONE ||
                state == TransactionState.STATE_COMMITTED ||
                // state == TransactionState.STATE_COMMITTED_ONE_PHASE_OK ||
                // state == TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK ||
                state == TransactionState.STATE_ROLLED_BACK) {

            // If the transaction is discarded, then ensure that
            // the log record is discarded.

            CoordinatorLog.removeLog(log.localTID);
            destroy();

        } else {

            // Otherwise continue with reconstruction.
            participants = new RegisteredResources(this);
            participants.reconstruct(log);

            // Reconstruct the SuperiorInfo object.  This will result in a
            // call to RecoveryManager.addCoordinator (which is done
            // because reconstruction of the object references in the
            // SuperiorInfo requires the Coordinator to
            // already be known to the RecoveryManager).

            superInfo = new SuperiorInfo();
            superInfo.reconstruct(log, this);

            // Cache the name  - create a buffer and print the
            // global XID into it.

            name = superInfo.globalTID.toString();

            // Cache the hash value of the Coordinator.

            hash = superInfo.globalTID.hashCode();
        }
    
synchronized Statusrecover(boolean[] isRoot)
Directs the TopCoordinator to perform recovery actions based on its reconstructed state after a failure, or after an in-doubt timeout has occurred. This method is called by the RecoveryManager during recovery, in which case there is no terminator object, or during normal operation if the transaction commit retry interval has been exceeded for the transaction. If this method is called more times than the retry limit specified in COMMITRETRY, then the global outcome of the transaction is taken from the value of HEURISTICDIRECTION.

param
isRoot A 1-element array which will be filled in with the root flag.
return
The state of the recovered transaction.
see


        Status result;

        // Determine the global outcome using the transactions state for a root
        // Coordinator, or the RecoveryCoordinator for a subordinate.

        if (superInfo.recovery != null) {

            // For a subordinate, first check whether the global
            // outcome is known locally.


            // GDH COP For the commit_one_phase operations we need to do the
            //         following ultimately. However for all c-o-p operations
            //         We know that the CLIENT/Superior chose to COMMIT.
            //         Also for all c-o-p operations that are  'past tense'
            //         the direction (commit or rolled back) is not really
            //         important as we are using c-o-p for single resources
            //         not last agent in CORBA CosTransactions.
            //
            // For clarity, all c-o-p states return a commited direction,
            // This is counter intuative but logicaly correct (unimportant)
            // even for COMMIT_ONE_PHASE_ROLLED_BACK.
            // A well behaved resource will not contact us in any of the
            // 'past tense' c-o-p states anyway as they have already returned
            // from a c-o-p op and can expect no further flows
            // (apart from forget perhaps).
            // When it comes to real resource flows we must be careful to
            // cause the following actions based on state:
            //
            // STATE_COMMITTING_ONE_PHASE
            // (We only ever enter this state if we have one resource
            // even if the c-o-p method was called on our CoordinatorResource)
            // The transaction was partway through a commit_one_phase
            // operation when the server failed.
            // So the commit_one_phase needs to be called again.
            // STATE COMMITTED_ONE_PHASE
            // STATE COMMITTED_ONE_PHASE_ROLLEDBACK
            // The transaction had just completed a commit_one_phase operation.
            // Therefore all of the work for the downstream part of the
            // transaction is over.  The only work to do is to possibly report
            // outcome to superior.
            // STATE COMMIT_ONE_PHASE_HEURISTIC_MIXED
            // STATE COMMIT_ONE_PHASE_HEURISTIC_HAZARD
            // Part of the tree has made a heuristic decision.  The forget
            // message must flow to all subordinate coordinators to allow them
            // to end.

            switch (tranState.state) {

            // GDH Due to the possibility of recovery being attempted
            // on more than one thread we must cover the case where
            // the transaction has actually COMMITTED already.

            case TransactionState.STATE_COMMITTED :
                // GDH (added)
            case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
                // GDH (added)
            case TransactionState.STATE_COMMITTING_ONE_PHASE :
                // GDH (added)
            case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :
                // GDH (added)
            case TransactionState.STATE_COMMITTING :
                result = Status.StatusCommitted;
                break;

            // GDH Due to the possibility of recovery being attempted
            // on more than one thread we must cover the case where
            // the transaction has actually ROLLED_BACK already.

            case TransactionState.STATE_ROLLED_BACK :  // GDH (added)
            case TransactionState.STATE_ROLLING_BACK :
                // GDH Note we do not need C-O-P_ROLLED_BACK Here as the actual
                // resource rolling back will be done already so it's academic.
                result = Status.StatusRolledBack;
                break;

            // For a subordinate, the replay_completion method is invoked on
            // the superior's RecoveryCoordinator.  We may need to create a
            // CoordinatorResource object to give to the superior in the case
            // where we are in recovery. If the number of times
            // the replay_completion has bee retried is greater than the value
            // specified by COMMITRETRY, then HEURISTICDIRECTION is used
            // to determine the transaction outcome.

            default :

                boolean attemptRetry = true;
                // String commitRetryVar;
                // int commitRetries = 0;

                // If COMMITRETRY is not set, then retry is infinite.
                // Otherwise check that
                // the current number of retries is less than the limit.

               /**
                commitRetryVar = Configuration.
                    getPropertyValue(Configuration.COMMIT_RETRY);
                if (commitRetryVar != null) {
                    try {
                        commitRetries = Integer.parseInt(commitRetryVar);
                    } catch( NumberFormatException exc ) {}

                    if (superInfo.resyncRetries() >= commitRetries) {
                        attemptRetry = false;
                    }
                }
                **/
                int commitRetries = Configuration.getRetries();
                if (commitRetries >= 0 && (superInfo.resyncRetries() >= commitRetries))
                    attemptRetry = false;


                if (!attemptRetry) {

                    // If we are not to attempt a retry of the
                    // replay_completion method, then the HEURISTICDIRECTION
                    // environment variable  is used to get the global outcome.

                    String heuristicVar;
                    boolean commitTransaction = false;
                    result = Status.StatusRolledBack;

                    heuristicVar =
                        Configuration.getPropertyValue(
                            Configuration.HEURISTIC_DIRECTION);

                    if (heuristicVar != null) {
                        commitTransaction = (heuristicVar.charAt(0) == '1");
                    }

                    if (commitTransaction) {
                        result = Status.StatusCommitted;
                    }

                } else {

                    // Otherwise, use the RecoveryCoordinator to get
                    // the global outcome. Get the global outcome
                    // from the superior's RecoveryCoordinator.

                    try {
						if(_logger.isLoggable(Level.FINE))
                    	{
							_logger.logp(Level.FINE,"TopCoordinator","recover",
									"Before invoking replay_completion on Superior Coordinator");
                    	}
                        if (!delegated) {
                            result = superInfo.recovery.
                                        replay_completion(superInfo.resource);
                        } else {
                            result = ((RecoveryCoordinatorImpl)(superInfo.recovery)).
                                        replay_completion(superInfo.resource, logPath);
                        }

                        // GDH
                        // If the global result is returned as COMMITTING we
                        // know the outcome of the global transaction
                        // is COMMITTED.

                        if (result == Status.StatusCommitting) {
                            result = Status.StatusCommitted;
                        }
                    } catch (Throwable exc) {
                        // If the exception is neither TRANSIENT or
                        // COMM_FAILURE, it isunexpected, so display a message
                        // and assume that the transaction has rolled back.

                        if (!(exc instanceof COMM_FAILURE) &&
                                !(exc instanceof TRANSIENT)) {
                            result = Status.StatusRolledBack;
                        } else {
                            // For TRANSIENT or COMM_FAILURE, the outcome
                            // is unknown.
                            result = Status.StatusUnknown;
                        }
                    }
                }

                break;
            }

            // Clear the root Coordinator flag to indicate that
            // this is not the root.

            root = false;

        } else {

            // For a top-level Coordinator, we will generally only
            // recover in the case where we have successfully prepared.
            // If the state is not prepared_success,
            // then assume it is rollback.

            if (tranState.state == TransactionState.STATE_PREPARED_SUCCESS) {
                result = Status.StatusCommitted;
            } else {
                result = Status.StatusRolledBack;
            }

            // Set the root Coordinator flag to indicate that this is the root.

            root = true;
        }

        isRoot[0] = root;

        return result;
    
public synchronized RecoveryCoordinatorregister_resource(Resource res)
Enables a Resource to be registered as a participant in the completion of the top-level transaction represented by the TopCoordinator. If the TopCoordinator is a subordinate, and has not registered with its superior, it creates a CoordinatorResource and registers it. The RecoveryCoordinator that is returned is stored in the SuperiorInfo.

param
res The Resource to be registered.
return
The RecoveryCoordinator object from the registration with the top-level ancestor.
exception
Inactive The Coordinator is completing the transaction and cannot accept this registration.
exception
TRANSACTION_ROLLEDBACK The transaction which the Coordinator represents has already been rolled back, or has been marked rollback-only.
see


        RecoveryCoordinator result = null;

        // First check the state of the transaction. If it is not active,
        // do not allow the registration.

        if (tranState == null || tranState.state !=
                TransactionState.STATE_ACTIVE) {
          Inactive exc = new Inactive();
          throw exc;
        }

        // Check whether the transaction has been marked rollback-only.

        if (rollbackOnly) {
            TRANSACTION_ROLLEDBACK exc =
                new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        // If not previously registered, a CoordinatorResource object must be
        // registered with our superior.  Note that root TopCoordinators are
        // created with the registration flag set, so we do not need to
        // check whether we are the root TopCoordinator here.

        if (!registered) {

            // Initialise the CoordinatorResource with the local id,
            // our reference, and a flag to indicate that it does not
            // represent a subtransaction.

            CoordinatorResourceImpl cImpl =
                new CoordinatorResourceImpl(superInfo.globalTID, this, false);

            try {

                // Register the CoordinatorResource with the superior
                // Coordinator, and store the resulting RecoveryCoordinator
                // reference.

                CoordinatorResource cRes = cImpl.object();
                RecoveryCoordinator superRecovery =
                    superInfo.superior.register_resource(cRes);
		if (!(superRecovery instanceof TxInflowRecoveryCoordinator))
                    superInfo.setRecovery(superRecovery);
                superInfo.setResource(cRes);
                registered = true;
				if(_logger.isLoggable(Level.FINEST))
                {
                    _logger.logp(Level.FINEST,"TopCoordinator","register_resource()",
							"CoordinatorResource " + cImpl + 
							" has been registered with (Root)TopCoordinator"+
							superInfo.globalTID.toString());
                }

            } catch (Exception exc) {

                // If an exception was raised, do not store the
                // RecoveryCoordinator or set the registration flag.
                // Throw an internal exception.

                cImpl.destroy();

                if (exc instanceof OBJECT_NOT_EXIST) {

                    // If the exception is a system exception, then allow it
                    // to percolate to the caller.
                    TRANSACTION_ROLLEDBACK ex2 =
                        new TRANSACTION_ROLLEDBACK(
                            0, CompletionStatus.COMPLETED_NO);
                    ex2.initCause(exc);
                    throw ex2;
                }

                if (exc instanceof Inactive)  {
                    throw (Inactive)exc;
                }

                if (exc instanceof SystemException) {
                    throw (SystemException)exc;
                }

                // Otherwise throw an internal exception.

                INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
                                            CompletionStatus.COMPLETED_NO);
                ex2.initCause(exc);
                throw ex2;
            }
        }

        // If the set has not already been created, create it now.

        if (participants == null) {
            participants = new RegisteredResources(logRecord, this);
        }

        // Add a duplicate of the reference to the set.  This is done
        // because if the registration is for a remote object, the proxy
        // will be freed when the registration request returns.

        // COMMENT(Ram J) if the res object is a local servant, there is
        // no proxy involved. Also, the instanceof operator could be replaced
        // by a is_local() method if this class implements the CORBA local
        // object contract.
        int numRes = 0;
        if (res instanceof OTSResourceImpl) {
            numRes = participants.addRes(res);
		    if(_logger.isLoggable(Level.FINEST))
            {
				_logger.logp(Level.FINEST,"TopCoordinator","register_resource()",
						"OTSResource " + res +" has been registered"+"GTID is:"+
						superInfo.globalTID.toString());
            }

        } else {
            numRes = participants.addRes((Resource)res._duplicate());
        }

        temporary = false;

        // Create, initialise and return a RecoveryCoordinator
        // object to the caller.

        // COMMENT(Ram J) a RecoveryCoordinator object need not be
        // created for local resources.
        if (!(res instanceof OTSResourceImpl)) {
            RecoveryCoordinatorImpl rcImpl = null;
            try {
                rcImpl = new RecoveryCoordinatorImpl(
                                            superInfo.globalTID, numRes);
                result = rcImpl.object();
            } catch (Exception exc) {

                // If the RecoveryCoordinator could not be created,
                // report the exception.

                INTERNAL ex2 = new INTERNAL(MinorCode.RecCoordCreateFailed,
                                            CompletionStatus.COMPLETED_NO);
                throw ex2;
            }

            // ADD(Ram J) memory leak fix. All Recovery Coordinators need
            // to be cleanedup when the transaction completes.
            if (recoveryCoordinatorList == null) {
                recoveryCoordinatorList = new Vector();
            }
            recoveryCoordinatorList.add(rcImpl);
        }

        return result;
    
public synchronized voidregister_subtran_aware(SubtransactionAwareResource sares)
Enables a SubtransactionAwareResource to be registered as a participant in the completion of a subtransaction. For a top-level transaction this raises the NotSubtransaction exception.

param
sares The SubtransactionAwareResource to be registered.
return
exception
NotSubtransaction The Coordinator represents a top-level transaction and cannot accept the registration.
see


        NotSubtransaction exc = new NotSubtransaction();
        throw exc;
    
public synchronized voidregister_synchronization(Synchronization sync)
Informs the TopCoordinator that the given object requires synchronization before and after completion of the transaction. If possible, a CoordinatorSync object is registered with the superior Coordinator. Otherwise this Coordinator becomes the root of a sub-tree for synchronization.

param
sync The Synchronization object to be registered.
return
exception
Inactive The Coordinator is in the process of completing the transaction and cannot accept this registration.
exception
SynchronizationUnavailable The transaction service cannot support synchronization.
exception
SystemException The operation failed.
see


        // First check the state of the transaction. If it is not active,
        // do not allow the registration.

        if (tranState == null ||
                tranState.state != TransactionState.STATE_ACTIVE) {
              Inactive exc = new Inactive();
              throw exc;
        }

        // If not previously registered, a CoordinatorSync object must be
        // registered with our superior.  Note that root TopCoordinators
        // are created with the registration flag set, so we do not need to
        // check whether we are the root TopCoordinator here.

        if (!registeredSync) {

            // Initialise the CoordinatorSync with the local id, our reference,
            // and a flag to indicate that does not represent a subtransaction.

            CoordinatorSynchronizationImpl sImpl =
                new CoordinatorSynchronizationImpl(this);

            // Register the CoordinatorSync with the superior CoordinatorImpl.

            try {
                Synchronization subSync = sImpl.object();
                superInfo.superior.register_synchronization(subSync);
                registeredSync = true;

                // added (Ram J) for memory leak fix.
                this.coordSyncImpl = sImpl;
				if(_logger.isLoggable(Level.FINER))
                {
					_logger.logp(Level.FINER,"TopCoordinator",
							"register_synchronization()", 
							"CoordinatorSynchronizationImpl :" + sImpl + 
							" has been registered with (Root)TopCoordinator"+
							"GTID is: "+ superInfo.globalTID.toString());
                }

            } catch (Exception exc) {
                // If an exception was raised, dont set the registration flag.
                sImpl.destroy();

                // If the exception is a system exception, then allow it
                // to percolate to the caller.

                if (exc instanceof OBJECT_NOT_EXIST) {
                    TRANSACTION_ROLLEDBACK ex2 =
                        new TRANSACTION_ROLLEDBACK(
                            0, CompletionStatus.COMPLETED_NO);
                    throw ex2;
                }

                if (exc instanceof Inactive) {
                    throw (Inactive)exc;
                }

                if (exc instanceof SystemException) {
                    throw (SystemException) exc;
                }

                // Otherwise throw an internal exception.

                INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
                                            CompletionStatus.COMPLETED_NO);
                throw ex2;
            }
        }

        // Make sure the RegisteredSyncs instance variable has been set up.

        if (synchronizations == null) {
            synchronizations = new RegisteredSyncs();
        }

        // Add a duplicate of the reference to the set.  This is done
        // because if the registration is for a remote object,
        // the proxy will be freed
        // when the registration request returns.

        // COMMENT(Ram J) if the sync object is a local servant, there is
        // no proxy involved. Also the instanceof operator could be replaced
        // by a is_local() method if this class implements the CORBA local
        // object contract.
        if (sync instanceof com.sun.jts.jta.SynchronizationImpl) {
            synchronizations.addSync(sync);

		    if(_logger.isLoggable(Level.FINER))
            {
				_logger.logp(Level.FINER,"TopCoordinator",
						"register_synchronization()",
						"SynchronizationImpl :" + sync +
						" has been registeredwith TopCoordinator :"+
						"GTID is : "+ superInfo.globalTID.toString().toString());
            }

        } else {
            synchronizations.addSync((Synchronization) sync._duplicate());
        }

        temporary = false;
    
synchronized booleanremoveChild(CoordinatorImpl child)
Removes the given Coordinator from the set of children of the target TopCoordinator. If the TopCoordinator is a temporary ancestor, and has no recoverable state after the child is removed, it destroys itself.

param
child The child Coordinator.
return
Indicates success of the operation.
see


        boolean result = false;

        // Remove the child from the set of children.  If the NestingInfo
        // instance variable has not been set up, then the child cannot
        // be removed.

        if (nestingInfo != null) {
            result = nestingInfo.removeChild(child);
        }

        // If the removal results in an empty, temporary Coordinator, then this
        // Coordinator must be cleaned up.  The RecoveryManager is called to
        // clean up the transaction.

        if (temporary && !registered &&
                !(participants != null && participants.involved()) &&
                !(synchronizations != null && synchronizations.involved()) &&
                !(nestingInfo != null && nestingInfo.numChildren() > 0)) {
            cleanUpEmpty(null);
        }

        return result;
    
synchronized CoordinatorImplreplyAction(int[] action)
Indicates that a method reply is being sent and requests the TopCoordinator's action. If the Coordinator has active children, which are not registered with their superior (includes root Coordinators) then this method returns activeChildren. If it has already been registered, the method returns doNothing. Otherwise the TopCoordinator returns forgetMe.

param
action A 1-element array to hold the reply action.
return
The parent coordinator if any.
exception
SystemException An error occurred. The minor code indicates the reason for the exception.
see


        CoordinatorImpl result = null;
        action[0] = CoordinatorImpl.doNothing;

        // If this Coordinator is not a root, and there are active children,
        // report that fact to the caller. If the NestingInfo instance variable
        // has not been set up, there are no children.

        if (!root && nestingInfo != null && nestingInfo.replyCheck()) {

            action[0] = CoordinatorImpl.activeChildren;

            // If there are no active children, then check whether this
            // transaction needs to be destroyed, or registered on reply.

        } else {

            // If there are participants, and we have not registered,
            // raise an exception.

            if (!registered) {
                if (participants != null && participants.involved()) {

                    INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
                                                CompletionStatus.COMPLETED_NO);
                    throw ex2;
                } else if (!registeredSync) {
                    action[0] = forgetMe;
                }
            }

            // If there are synchronization objects, and we have not
            // registered, raise an exception.

            if (!registeredSync) {
                if (synchronizations != null && synchronizations.involved()) {

                    INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
                                                CompletionStatus.COMPLETED_NO);
                    throw ex2;
                } else if (action[0] == doNothing && !registered) {
                    // If we are not registered, and have no participants,
                    // we have no reason to exist, so tell the caller to
                    // forget about us. The TransactionManager will take
                    // care of cleaning everything else up when
                    // it receives the forgetMe response.
                    action[0] = forgetMe;
                }
            }
        }

        // Default action is do nothing when we are registered.

        result = null;

        return result;
    
voidrollback(boolean force)
Directs the TopCoordinator to roll back the transaction. The TopCoordinator directs all registered Resources to rollback. If any Resources raise Heuristic exceptions, the information is recorded, and the Resources are directed to forget the transaction before the Coordinator returns a heuristic exception to its caller.

param
force Indicates that the transaction must rollback regardless.
return
exception
HeuristicMixed A Resource has taken an heuristic decision which has resulted in part of the transaction being committed.
exception
HeuristicHazard Indicates that heuristic decisions may have been taken which have resulted in part of the transaction being rolled back.
see


        // Until we actually distribute prepare flows, synchronize the method.

        synchronized(this){
		if(_logger.isLoggable(Level.FINE))
		{
			_logger.logp(Level.FINE,"TopCoordinator","rollback()",
					"Within TopCoordinator.rollback() :"+"GTID is : "+
					superInfo.globalTID.toString());
        }

            // If the transaction has already been rolled back, just return.

            if (tranState == null) {
                return;
            }

            // GDH
            // If the TopCoordinator has already completed (eg due to
            // recovery resync thread and this is now running on
            // the 'main' one) we can safely ignore the error

            if (tranState.state == TransactionState.STATE_ROLLED_BACK) {
                return;
            }

            // GDH
            // The state could even be commited, which can be OK if it was
            // committed, and thus completed, when the recovery thread asked
            // the superior about the txn. The superior would
            // no longer had any knowledge of it. In this case, due to presumed
            // abort, the recovery manager would then
            // now default to aborting it.
            // In this case if the TopCoordinator has committed already
            // we should also just return ignoring the error.

            if (tranState.state == TransactionState.STATE_COMMITTED) {
                return;
            }

            // If this is not a forced rollback and the coordinator
            // has prepared or is in an inappropriate state, do not continue
            // and return FALSE.

            if (!force && ((tranState.state ==
                                TransactionState.STATE_PREPARED_SUCCESS) ||
                           (!tranState.setState(
                                TransactionState.STATE_ROLLING_BACK))
                          )) {
                return;
            }

            // We do not care about invalid state changes as we are
            // rolling back anyway. If the TopCoordinator is
            //  temporary, we do not change state as this would
            // cause a log force in a subordinate, which is not required.

            if( !temporary &&
                    !tranState.setState(TransactionState.STATE_ROLLING_BACK)) {
                // empty
            }

            // Rollback outstanding children.  If the NestingInfo instance
            // variable has not been created, there are no
            // children to rollback.

            if (nestingInfo != null) {
                nestingInfo.rollbackFamily();
            }

            // Release the lock before proceeding with rollback.

        }

        // Roll back all participants.  If a fatal error occurs during
        // this method, then the process must be ended with a fatal error.

        Throwable heuristicExc = null;
        if (participants != null) {
            try {
                participants.distributeRollback(false);
            } catch(Throwable exc) {

                if (exc instanceof HeuristicMixed ||
                        exc instanceof HeuristicHazard) {
                    heuristicExc = exc;
                }

                // ADDED (Ram J) percolate up any system exception.
                if (exc instanceof INTERNAL) {
                    throw (INTERNAL) exc;
                }
            }
        }

        // The remainder of the method needs to be synchronized.

        synchronized(this) {

            // Set the state.  Only bother doing this if the coordinator
            // is not temporary.

            if (!temporary &&
                    !tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
                // empty
            }

            // Clean up the TopCoordinator after a rollback.
            // In the case where the TopCoordinator is a root,
            // the CoordinatorTerm object must be informed that the transaction
            // has completed so that if another caller has rolled back
            // the transaction (time-out for example) the object normally
            // responsible for terminating the transaction can take the
            // appropriate action. NOTE: This may DESTROY
            // the TopCoordinator object so NO INSTANCE VARIABLES
            // should be referenced after the call. In the case where
            // the TopCoordinator is a subordinate, the CoordinatorResource
            // object must be informed that the transaction has been
            // completed so that it can handle any subsequent requests for the
            // transaction.

            if (terminator != null) {
                terminator.setCompleted(true, heuristicExc != null);
            }

            /* commented out (Ram J) for memory leak fix.
            // If there are no registered Synchronization objects, there is
            // nothing left to do, so get the RecoveryManager to forget
            // about us, then self-destruct.

            if (!root && (synchronizations == null ||
                          !synchronizations.involved())
                         ) {
                RecoveryManager.removeCoordinator(superInfo.globalTID,
                                                  superInfo.localTID,
                                                  true);

                if (!dying) {
                    destroy();
                }
            }
            */
            // added (Ram J) for memory leak fix
            // if subordinate, send out afterCompletion. This will
            // destroy the CoordinatorSynchronization and coordinator.
            if (!root) {
                afterCompletion(Status.StatusRolledBack);
            }

            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON.     */
            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

            // If there was heuristic damage, report it.

            if (heuristicExc != null) {
                if (heuristicExc instanceof HeuristicMixed) {
                    throw (HeuristicMixed) heuristicExc;
                } else {
                    throw (HeuristicHazard) heuristicExc;
                }
            }
        }

        // Otherwise return normally.
    
public voidrollback_only()
Ensures that the transaction represented by the target TopCoordinator cannot be committed.

param
return
exception
Inactive The Coordinator is already completing the transaction.
see


        if (tranState == null ||
                tranState.state != TransactionState.STATE_ACTIVE) {
            Inactive exc = new Inactive();
            throw exc;
        } else {
            // Set the rollback-only flag.
            rollbackOnly = true;
        }
    
synchronized java.lang.LongsetPermanent()
Marks the TopCoordinator as permanent.

param
return
The local transaction identifier.
see


        Long result = superInfo.localTID;
        temporary = false;
        return result;
    
synchronized voidsetTerminator(CompletionHandler term)
Informs the TopCoordinator of the identity of the object that is normally responsible for directing it through termination. The CoordinatorTerm / CoordinatorResource object is informed by the Coordinator when the transaction aborts so that they can cope with asynchronous aborts.

param
term The object normally responsible for terminating the Coordinator.
return
see

        terminator = term;