alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (SubCoordinator.java)

This example Glassfish source code file (SubCoordinator.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

coordinator, coordinatorimpl, coordinatorimpl, corba, inactive, inactive, invalid_transaction, invalid_transaction, log, logging, logicerrorexception, status, string, subcoordinator, systemexception, systemexception, transaction_rolledback, util

The Glassfish SubCoordinator.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

//----------------------------------------------------------------------------
//
// Module:      SubCoordinator.java
//
// Description: Nested transaction Coordinator object implementation.
//
// Product:     com.sun.jts.CosTransactions
//
// Author:      Simon Holdsworth
//
// Date:        March, 1997
//
// Copyright (c):   1995-1997 IBM Corp.
//
//   The source code for this program is not published or otherwise divested
//   of its trade secrets, irrespective of what has been deposited with the
//   U.S. Copyright Office.
//
//   This software contains confidential and proprietary information of
//   IBM Corp.
//----------------------------------------------------------------------------

package com.sun.jts.CosTransactions;

import java.util.*;

import org.omg.CORBA.*;
import org.omg.CosTransactions.*;

import com.sun.jts.codegen.otsidl.*;
import java.util.logging.Logger;
import java.util.logging.Level;
import com.sun.logging.LogDomains;
import com.sun.jts.utils.LogFormatter;

/**
 * The SubCoordinator interface is our implementation of the standard
 * Coordinator interface that is used for subtransactions. It allows
 * SubtransactionAwareResources to be registered for participation in a
 * subtransaction. 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 does not need to be
 * reconstructible in the case of a failure as subtransactions are not
 * durable.
 *
 * @version 0.01
 *
 * @author Simon Holdsworth, IBM Corporation
 *
 * @see
 */

//----------------------------------------------------------------------------
// CHANGE HISTORY
//
// Version By     Change Description
//   0.01  SAJH   Initial implementation.
//----------------------------------------------------------------------------

class SubCoordinator extends CoordinatorImpl {
    String              name = null;
    RegisteredResources participants = null;
    SuperiorInfo        superInfo = null;
    NestingInfo         nestingInfo = null;
    TransactionState    tranState = null;
    CompletionHandler   terminator = null;
    boolean             registered = false;
    boolean             root = true;
    boolean             rollbackOnly = false;
    boolean             dying = false;
    boolean             temporary = false;
    int                 hash = 0;
	/*
		Logger to log transaction messages
	*/  
    static Logger _logger = LogDomains.getLogger(SubCoordinator.class,LogDomains.TRANSACTION_LOGGER);


    /**
     * Creates and initialises a SubCoordinator, given the parent's local
     * and global identifiers and the sequence of ancestors.
     *
     * @param parentGlobalTID  The parent's global transaction identifier.
     * @param parentLocalTID   The parent's local transaction identifier.
     * @param ancestors        This transactions's ancestors (includes parent).
     *
     * @return
     *
     * @exception LogicErrorException  An internal logic error occurred.
     *
     * @see
     */
    SubCoordinator(GlobalTID parentGlobalTID, Long parentLocalTID,
            CoordinatorImpl[] ancestors) throws LogicErrorException {

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

        tranState = new TransactionState(parentLocalTID, parentGlobalTID);

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

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

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

        name = superInfo.globalTID.toString();

        // Cache the hash code.

        hash = superInfo.globalTID.hashCode();

        // Create the nesting info object to record the ancestors.

        nestingInfo = new NestingInfo(ancestors);

        // Zero out the RegisteredResources reference as it will be
        // created when needed.

        participants = null;

        // Set other instance variables.

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

        // Set the state of the subtransaction 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 {
            // Inform the RecoveryManager of the existence of this transaction.
            RecoveryManager.addCoordinator(tranState.globalTID,
                                           tranState.localTID, this, 0);
        }
    }

    /**
     * Creates and initialises a subordinate SubCoordinator, given the global
     * identifier, a reference to the superior SubCoordinator,
     * and the ancestors of the transaction.
     * The temporary subordinate indicator is used for the case where a parent
     * Coordinator is created when a subtransaction enters a process for the
     * first time. If the request returns and the subtransaction has no
     * participants, it is destroyed, along with any temporary ancestors.
     *
     * @param globalTID  The global identifier for the transaction.
     * @param superior   The superior Coordinator.
     * @param temporary  The temporary flag.
     * @param ancestors  The ancestors of the transaction.
     *
     * @return
     *
     * @exception LogicErrorException  An internal logic error occurred.
     *
     * @see
     */
    SubCoordinator(GlobalTID globalTID, Coordinator superior,
            boolean temporary, CoordinatorImpl[] ancestors)
            throws LogicErrorException {

        // 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,null);

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

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

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

        name = superInfo.globalTID.toString();

        // Cache the hash code.

        hash = superInfo.globalTID.hashCode();

        // Create the nesting info object to record the ancestors.

        nestingInfo = new NestingInfo(ancestors);

        // Zero out the RegisteredResources reference,
        // as it will be created when needed.

        participants = null;

        // Set other instance variables.

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

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

        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, 0)) {
            LogicErrorException exc =
                new LogicErrorException(
					LogFormatter.getLocalizedMessage(_logger,
					"jts.transaction_id_already_in_use"));
            throw exc;
        }
    }

    /**
     * Cleans up the state of the object.
     *
     * @param
     *
     * @return
     *
     * @see
     */
    public void doFinalize() {

        // 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 :
            rollback(true);
            break;

        // For committed or rolled-back, we really need to destroy the object

        case TransactionState.STATE_COMMITTED :
        case TransactionState.STATE_ROLLED_BACK :
            // if( tranState != null ) tranState.finalize();
            if( superInfo != null ) superInfo.doFinalize();
            // if( nestingInfo != null ) nestingInfo.finalize();
            // if( participants != null ) participants.finalize();

            tranState = null;
            superInfo = null;
            nestingInfo = null;
            participants = 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;
        }
    }

    /**
     * Returns the local status of the target transaction.
     *
     * @param
     *
     * @return  The status of the transaction.
     *
     * @see
     */
    synchronized public Status get_status() {

        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 :
                result = Status.StatusPreparing;
                break;
            case TransactionState.STATE_COMMITTING :
                result = Status.StatusCommitting;
                break;
            case TransactionState.STATE_COMMITTED :
                result = Status.StatusCommitted;
                break;
            case TransactionState.STATE_ROLLING_BACK :
                result = Status.StatusRollingBack;
                break;
            case TransactionState.STATE_ROLLED_BACK :
                result = Status.StatusRolledBack;
                break;

            // Any other state, return unknown.

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

        return result;
    }

    /**
     * Gets the local state of the parent transaction.
     * This operation references no instance variables and so can be
     * implemented locally in the proxy class.
     *
     * @param
     *
     * @return  The parent transaction's status.
     *
     * @exception SystemException  The parent could not be reached.
     *
     * @see
     */
    synchronized public Status get_parent_status() throws SystemException {

        Status result = Status.StatusNoTransaction;

        // Return the parents status.  If there is none, this is an error;
        // return no transaction status (may want to raise a LogicError here).

		if (tranState != null) {
			CoordinatorImpl parent = nestingInfo.getParent(false); 
			if (parent != null) { 
				result = parent.get_status();
			}
		} else {
			INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
				MinorCode.Completed, CompletionStatus.COMPLETED_NO); 
			throw exc; 
		}

        return result;
    }

    /**
     * Gets the local state of the top-level transaction.
     * This operation references no instance variables and so can be
     * implemented locally in a proxy class.
     *
     * @param
     *
     * @return  The top-level transaction status.
     *
     * @exception SystemException  The top-level ancestor could not be reached.
     *
     * @see
     */
    synchronized public Status get_top_level_status() throws SystemException {

        // Return the top-level status.  If there is none, this is an error;
        // return no transaction status (may want to raise a LogicError here).

        Status result = Status.StatusNoTransaction;

        if (tranState != null) {
            CoordinatorImpl topLevel = nestingInfo.getTopLevel();
            if (topLevel != null) {
                result = topLevel.get_status();
            }
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                MinorCode.Completed, CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    }

    /**
     * Compares the given Coordinator object with the target,
     * and returns TRUE if they represent the same transaction.
     * This operation needs to be implemented in an efficient manner, without
     * any cross-process calls. This could be achieved by including the
     * global identifier in the Coordinator references and comparing them.
     * This operation references no instance variables and so can be
     * implemented locally in a proxy class.
     *
     * @param other  The other Coordinator to be compared.
     *
     * @return  Indicates equality of the transactions the objects
     *   represent.
     *
     * @exception SystemException  The other Coordinator could not be reached.
     *
     * @see
     */
    synchronized public boolean is_same_transaction(Coordinator other)
            throws SystemException {

        boolean result = false;

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

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

        return result;
    }

    /**
     * Determines whether the target SubCoordinator is related to
     * the given Coordinator (i.e. is a member of the same transaction family).
     * For a subtransaction this is equivalent to saying that the transaction
     * associated with the parameter object is a descendant of the top-level
     * ancestor 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
     */
    synchronized public boolean is_related_transaction(Coordinator other)
            throws SystemException {

        // Check whether the given transaction is a descendant of our top-level
        // transaction.

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

        return result;
    }

    /**
     * Determines whether the target SubCoordinator is an ancestor
     * of the given Coordinator.
     * 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
     */
    public boolean is_ancestor_transaction(Coordinator other)
            throws SystemException {

        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;
    }

    /**
     * Determines whether the target SubCoordinator is a descendant
     * of the given Coordinator.
     * 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
     */
    synchronized public boolean is_descendant_transaction(Coordinator other)
            throws SystemException {

        // A transaction is considered to be a descendant of itself, so if the
        // two transactions are the same, return TRUE.

        boolean result = false;
        if (tranState != null) {
            if (is_same_transaction(other)) {
                result = true;
            } else {
            // Otherwise, go through our ancestors, comparing
            // them with the given transaction.
            result = nestingInfo.isDescendant(other);
            }
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                MinorCode.Completed, CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    }

    /**
     * Determines whether the target SubCoordinator represents a top-level
     * (non-nested) transaction.
     * <p>
     * For a subtransaction returns FALSE.
     * <p>
     * This operation references no instance variables and so can be
     * implemented locally in a proxy class.
     *
     * @param
     *
     * @return  Indicates the transaction is top-level.
     *
     * @see
     */
    public boolean is_top_level_transaction() {

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

        return result;
    }

    /**
     * Returns a hash value based on the transaction associated with the target
     * object.
     *
     * @param
     *
     * @return  The hash value for the transaction.
     *
     * @see
     */
    synchronized public int hash_transaction() {

        int result =  hash;

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

        return result;
    }

    /**
     * Returns a hash value based on the top-level ancestor of the transaction
     * associated with the target object.
     *
     * @param
     *
     * @return  The hash value for the top-level ancestor.
     *
     * @exception SystemException  The other Coordinator could not be reached.
     *
     * @see
     */
    synchronized public int hash_top_level_tran() throws SystemException {

        int result = 0;
        if (tranState != null) {
            CoordinatorImpl topLevel = nestingInfo.getTopLevel();
            if (topLevel != null) {
                result = topLevel.hash_transaction();
            }
        } else {
            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
                MinorCode.Completed, CompletionStatus.COMPLETED_NO);
            throw exc;
        }

        return result;
    }

    /**
     * Enables a Resource to be registered as a participant in the completion
     * of the subtransaction represented by the SubCoordinator.
     * If the Resource is a SubtransactionAwareResource, it is registered
     * with the SubCoordinator; if the SubCoordinator has not registered
     * with is superior, it creates a CoordinatorResource and registers it
     * with the superior. The registration is passed on to the top-level
     * Coordinator in any case.
     *
     * @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  been marked
     *   rollback-only.
     * @exception SystemException  The operation failed.
     *
     *  @see
     */
    synchronized public RecoveryCoordinator register_resource(Resource res)
            throws SystemException, Inactive, TRANSACTION_ROLLEDBACK {

        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;
        }

        // Register the given Resource with the top-level
        // Coordinator first, and remember the RecoveryCoordinator object
        // that is returned by the top-level Coordinator.

        CoordinatorImpl topLevel = nestingInfo.getTopLevel();

        // If the top-level Coordinator raises an exception, then do not
        // proceed with the registration, and return the exception.

        try {
            result = topLevel.register_resource(res);
        } catch (SystemException exc) {
            throw (SystemException) exc.fillInStackTrace();
        } catch (Inactive exc) {
            throw (Inactive) exc.fillInStackTrace();
        }

        // Find out whether the Resource is actually a
        // SubtransactionAwareResource.

        boolean subAwareRes =
            res._is_a(SubtransactionAwareResourceHelper.id());

        // If the Resource is actually a SubtransactionAwareResource,
        // then it needs to be registered for participation in completion
        // of the subtransaction as well as the top level transaction.

        if (subAwareRes) {

            // If not previously registered, a CoordinatorResource object
            // must be registered with our superior.  Note that root
            // SubCoordinators are created with the registration flag set,
            // so we do not need to check
            // whether we are the root SubCoordinator 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, true);

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

                try {
                    CoordinatorResource cRes = cImpl.object();
                    superInfo.superior.register_subtran_aware(cRes);
                    superInfo.setResource(cRes);
                    registered = true;
                } catch (Throwable exc) {
                    // If an exception was raised, do not set the
                    // registration flag, and destroy the object.
                    cImpl.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;
                }
            }

            // Add the SubtransactionAwareResource to the set of participants.
            // Make sure the RegisteredResources instance variable has been
            // set up.

            if (participants == null) {
                participants = new RegisteredResources(null, 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.

            participants.addRes((Resource)res._duplicate());
            temporary = false;
        }

        return result;
    }

    /**
     * Enables a SubtransactionAwareResource to be registered as a participant
     * in the completion of a subtransaction.
     * <p>
     * If the SubCoordinator has not registered with is superior, it creates a
     * CoordinatorResource and registers it with the superior.
     *
     * @param sares  The SubtransactionAwareResource to be registered.
     *
     * @return
     *
     * @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.
     * @exception SystemException  The operation failed.
     *
     * @see
     */
    synchronized public void register_subtran_aware(
            SubtransactionAwareResource sares)
            throws SystemException, Inactive, TRANSACTION_ROLLEDBACK {

        // 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 SubCoordinators
        // are created with the registration flag set, so we do not need
        // to check whether we are the root SubCoordinator 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, true);

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

            try {
                CoordinatorResource cRes = cImpl.object();
                superInfo.superior.register_subtran_aware(cRes);
                superInfo.setResource(cRes);
                registered = true;
            } catch(Throwable exc) {
                // If an exception was raised, do not set the registration flag.
                cImpl.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;
            }
        }

        // Add the SubtransactionAwareResource to the set of participants.
        // Make sure the RegisteredResources instance variable has been set up.

        if (participants == null) {
            participants = new RegisteredResources(null, 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.

        participants.addRes((Resource)sares._duplicate());
        temporary = false;
    }

    /**
     * Ensures that the transaction represented by the target SubCoordinator
     * cannot be committed.
     *
     * @param
     *
     * @return
     *
     * @exception Inactive  The Coordinator is already completing the
     *                      transaction.
     * @see
     */
    synchronized public void rollback_only() throws Inactive {

        if (tranState.state != TransactionState.STATE_ACTIVE) {
            Inactive exc = new Inactive();
            throw exc;
        } else {
            // Set the rollback-only flag.
            rollbackOnly = true;
        }
    }

    /**
     * Returns a printable string that represents the SubCoordinator.
     * This operation references only the global TID, and so can be
     * implemented locally in a proxy class.
     *
     * @param
     *
     * @return  The transaction name.
     *
     * @see
     */
    synchronized public String get_transaction_name() {

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

            throw exc;
        }

        return result;
    }

    /**
     * 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
     */
    synchronized public Control create_subtransaction() throws Inactive {

        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 SubCoordinator
        // 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[] thisAncestors = nestingInfo.getAncestors();
        CoordinatorImpl[] ancestors =
            new CoordinatorImpl[thisAncestors.length + 1];
        System.arraycopy(thisAncestors, 0, ancestors, 1, thisAncestors.length);
        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.

        nestingInfo.addChild(child);

        return result;
    }

    /**
     * Returns a global identifier that represents the SubCoordinator's
     * transaction. <p>
     * This operation references only the global identifier, and so can be
     * implemented locally in a proxy class.
     * <p>
     * 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 identifier for the transaction.
     *
     * @see
     */
    public otid_t getGlobalTID() {

        otid_t result = null;
        result = superInfo.globalTID.realTID;

        return result;
    }

    /**
     * Returns the internal identifier for the transaction.
     * This method is currently not synchronized because that causes a deadlock
     * in resync.
     *
     * @param
     *
     * @return  The local transaction identifier.
     *
     * @see
     */
    public long getLocalTID() {

        long result = superInfo.localTID.longValue();
        return result;
    }

    /**
     * Indicates that a method reply is being sent and requests the
     * SubCoordinator'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 SubCoordinator 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
     */
    synchronized CoordinatorImpl replyAction(int[/*1*/] action)
            throws SystemException {

        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.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 {
                    action[0] = forgetMe;
                }
            }

            // 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 whenit receives the forgetMe
            // response.

            if (action[0] == doNothing && !registered)
                action[0] = forgetMe;
        }

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

        result = null;

        return result;
    }

    /**
     * Marks the SubCoordinator as permanent.
     *
     * @param
     *
     * @return  The local transaction identifier.
     *
     * @see
     */
    synchronized Long setPermanent() {

        Long result = superInfo.localTID;
        temporary = false;

        return result;
    }

    /**
     * Checks whether the SubCoordinator is marked rollback-only.
     *
     * @param
     *
     * @return  Indicates whether the transaction is rollback-only.
     *
     * @see
     */
    synchronized public boolean isRollbackOnly() {

        boolean result = rollbackOnly;
        return result;
    }

    /**
     * Checks whether the SubCoordinator is active.
     *
     * @param
     *
     * @return  Indicates the transaction is active.
     *
     * @see
     */
    synchronized boolean isActive() {

        boolean result = (tranState.state == TransactionState.STATE_ACTIVE);
        return result;
    }

    /**
     * Checks whether the SubCoordinator has registered with its superior.
     *
     * @param
     *
     * @return  Indicates the registration status.
     *
     * @see
     */
    synchronized boolean hasRegistered() {

        boolean result = registered;
        return result;
    }

    /**
     * Returns the sequence of ancestors of the transaction.
     *
     * @param
     *
     * @return  The sequence of ancestors.
     *
     * @see
     */
    synchronized public TransIdentity[] getAncestors() {

        CoordinatorImpl[] coords = nestingInfo.getAncestors();

        TransIdentity[] result = new TransIdentity[coords.length];
        for (int i = 0; i < coords.length; i++) {
            try {
                result[i] = new TransIdentity(coords[i].object(), null,
                                              coords[i].getGlobalTID());
            } catch (Throwable exc) {}
        }

        return result;
    }

    /**
     * Adds the given Coordinator reference to the set of children
     * of the target SubCoordinator.
     *
     * @param child  The child Coordinator.
     *
     * @return  Indicates success of the operation.
     *
     * @see
     */
    synchronized boolean addChild(CoordinatorImpl child) {

        boolean result = nestingInfo.addChild(child);
        return result;
    }

    /**
     * Removes the given Coordinator from the set of children of the target
     * SubCoordinator.
     * If the SubCoordinator 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
     */
    synchronized boolean removeChild(CoordinatorImpl child) {

        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.

        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()) &&
                !(nestingInfo != null && nestingInfo.numChildren() > 0)) {

            // We pass the parent Coordinator to the RecoveryManager
            // so that it can remove the child from the parent's set of
            // children after the child is rolled back.

            CoordinatorImpl parent = nestingInfo.getParent(true);
            cleanUpEmpty(parent);
        }

        return result;
    }

    /**
     * Directs the SubCoordinator to prepare to commit.
     * The SubCoordinator checks that the subtransaction can be committed.
     * It does not distribute prepare operations to the participants.
     *
     * @param
     *
     * @return  The consolidated vote.
     *
     * @exception INVALID_TRANSACTION  The transaction is not in a
     *   state to commit, due to outstanding work.
     *
     * @see
     */
    static String[] resultName = { "Commit"/*#Frozen*/, "Rollback"/*#Frozen*/, "Read-only"/*#Frozen*/ };

    synchronized Vote prepare() throws INVALID_TRANSACTION {

        Vote result = Vote.VoteRollback;
        int newState = TransactionState.STATE_PREPARED_FAIL;

        // Record that the Coordinator is about to prepare.

        // 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.numChildren() != 0) {
            INVALID_TRANSACTION exc =
                new INVALID_TRANSACTION(MinorCode.UnfinishedSubtransactions,
                                        CompletionStatus.COMPLETED_NO);
                throw exc;
        }

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

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

        // Check for marked rollback-only.

        if (rollbackOnly) {

            // Record that the Coordinator is deciding to rollback.
            // Try to set the state to prepared fail.

            if (!tranState.setState(TransactionState.STATE_PREPARED_FAIL)) {
                return Vote.VoteRollback;
            }
        } else {
            newState = TransactionState.STATE_PREPARED_SUCCESS;
            result = Vote.VoteCommit;
        }

        // Record that prepare is complete.
        // Set the state.

        if (!tranState.setState(newState)) {
            result = Vote.VoteRollback;
        }

        return result;
    }

    /**
     * Directs the SubCoordinator to commit the transaction.
     * The SubCoordinator directs all registered Resources to commit.
     *
     * @param
     *
     * @return
     *
     * @see
     */
    void commit() {

        Coordinator parent = null;

        // Record that the Coordinator is about to commit.
        // Until we actually distribute commit flows, synchronize the method.

        synchronized (this) {

            // If the SubCoordinator 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);
            }

            // Get the reference of the parent Coordinator.

            parent = nestingInfo.getParent(false).object();

            // 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.

        if (participants != null) {
            try {
                participants.distributeSubcommit(parent);
            } catch (Throwable exc) {
				_logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
                        new java.lang.Object[] { exc.toString(),
						"commit"});
				 String msg = LogFormatter.getLocalizedMessage(_logger,
				 							"jts.exception_on_resource_operation",
											new java.lang.Object[]
											{exc.toString(),
											"commit"});
				 throw  new org.omg.CORBA.INTERNAL(msg);
            }
        }

        // 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);
            }

            // Remove our reference from the parents set of children

            nestingInfo.removeFromParent(this);

            // Clean up the SubCoordinator after a commit.
            // In the case where the SubCoordinator 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 SubCoordinator object so NO INSTANCE VARIABLES
            // should be referenced after the call.
            // In the case where the SubCoordinator 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, false);
            }

            // As subtransactions do not have synchronization,
            // there is nothing left to  do, so get the
            //RecoveryManager to forget about us, then self-destruct.

            RecoveryManager.removeCoordinator(superInfo.globalTID,
                                              superInfo.localTID, false);
            destroy();

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

        }
    }

    /**
     * Directs the SubCoordinator to roll back the transaction.
     * The SubCoordinator directs all registered Resources to rollback.
     *
     * @param force
     *
     * @return
     *
     * @see
     */
    void rollback(boolean force) {

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

        synchronized (this) {

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

            if (tranState == null) {
                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 SubCoordinator 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 roll back.

            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.

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

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

        synchronized(this) {

            // Set the state to rolled back.

            // Remove our reference from the parents set of children
            if (!temporary &&
                    !tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
                // empty
            }

            nestingInfo.removeFromParent(this);

            // Clean up the SubCoordinator after a rollback.
            // In the case where the SubCoordinator 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 SubCoordinator object
            // so NO INSTANCE VARIABLES should be referenced after the call.
            // In the case where the SubCoordinator 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, false);
            }

            // As subtransactions do not have synchronization,
            // there is nothing left to do, so get the RecoveryManager
            // to forget about us, then self-destruct.

            RecoveryManager.removeCoordinator(superInfo.globalTID,
                                              superInfo.localTID, false);

            if (!dying) {
                destroy();
            }

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

    /**
     * Informs the SubCoordinator that the given object
     * requires synchronization before and after completion
     * of the top-level ancestor transaction.
     * The registration is passed directly to the top-level ancestor.
     *
     * @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.
     *
     * @see
     */
    synchronized public void register_synchronization(Synchronization sync)
            throws Inactive, SynchronizationUnavailable {

        // 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;
          }

        // Register the Synchronization object with the top-level Coordinator.
        // Allow any exception to percolate to the caller.

        CoordinatorImpl topLevel = nestingInfo.getTopLevel();
        topLevel.register_synchronization(sync);
    }

    /**
     * Informs the SubCoordinator 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
     */
    synchronized void setTerminator(CompletionHandler term) {
        terminator = term;
    }

    /**
     * Gets the parent coordinator of the transaction.
     *
     * @param
     *
     * @return  The parent Coordinator
     *
     * @see
     */
    Coordinator getParent() {

        Coordinator result = nestingInfo.getParent(false).object();
        return result;
    }

    /**
     * Gets the superior Coordinator for this transaction.
     *
     * @param
     *
     * @return  The superior Coordinator
     *
     * @see
     */
    Coordinator getSuperior() {

        Coordinator result = superInfo.superior;
        return result;
    }

   /**
    * Returns the Resource objects and their states.
    *
    * @param resources  The object which will contain the Resources
    * @param states     The object which will contain the states.
    *
    * @return
    *
    * @see
    */
    /* COMMENT(Ram J) only Admin package needs this.
    public void getResources(ResourceSequenceHolder resources,
            ResourceStatusSequenceHolder states) {

        if (participants != null) {
            participants.getResources(resources, states);

            // Validate each of the Resource objects in
            // the list before returning it.

            for (int i = 0; i < resources.value.length; i++) {
                if (resources.value[i]._non_existent()) {
                    resources.value[i] = null;
                }
            }
        } else {
            resources.value = null;
            states.value = null;
        }
    }
    */
    
    /**
     * Gets the object normally responsible for terminating this Coordinator.
     *
     * @param
     *
     * @return  The object normally responsible for terminating
     *   the Coordinator.
     *
     * @see
     */
    CompletionHandler getTerminator() {

        CompletionHandler result = terminator;
        return result;
    }

    private static Any emptyData = null;

    /**
     * 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
     */
    synchronized public PropagationContext get_txcontext() throws Unavailable {

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

        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);
        TransIdentity[] parents = getAncestors();

        // 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,
                                                           parents, emptyData);

        return result;
    }

    /**
     * Cleans up an empty Coordinator.
     *
     * @param parent  The parent Coordinator, if any.
     *
     * @return
     *
     * @see
     */
    void cleanUpEmpty(CoordinatorImpl parent) {

        // Roll the transaction back, ignoring any exceptions.

        try {
            rollback(true);
        } catch (Throwable exc) {}

        // If the transaction is a subtransaction, remove the
        // child from the parent's  set of children.
        // If the parent is temporary, this will cause the parent
        // to call cleanup_empty_coordinator, and so-on until all
        // empty ancestors are cleaned up.

        if (parent != null) {
            parent.removeChild(this);
        }
    }

    /**
     * Directs the SubCoordinator to commit the transaction in one phase
     * The SubCoordinator directs all registered Resources to commit.
     *
     * @param
     *
     * @return
     *
     * @see
     */
    boolean commitOnePhase() {

        // The commit of a subtransaction is always a one phase commit.
        // The implementation of the prepare/commit methods simply
        // split this up into two parts: the prepare checks the state and
        // the commit calls the resources.  Therefore commit_one_phase can
        // simply call these methods directly.
        // Also we let any exception pass up through.

        Vote v = this.prepare();

        if (v == Vote.VoteCommit) {
           this.commit();
        } else if (v == Vote.VoteReadOnly) {
            // Nothing to do
        } else {
            this.rollback(true);
        }

        return true;
    }

    /**
     * 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
     */
    public int hashCode() {
        return hash;
    }

    /**
     * Determines equality of the object with the parameter.
     * <p>
     * This relies on the availability of the propagation context from the
     * target Coordinator.
     * <p>
     * If the other Coordinator is remote, and not a JCoordinator,
     * and is in the process of ending the transaction,
     * then this operation will fail; in this
     * case we throw the INVALID_TRANSACTION exception with a minor code that
     * indicates the cause of the failure.
     * <p>
     * Unfortunately this is the best we can do with the OMG interfaces when
     * interoperating with a different OTS implementation.
     *
     * @param other  The other object.
     *
     * @return  Indicates equality.
     *
     * @see
     */
    public boolean equals(java.lang.Object other) throws INVALID_TRANSACTION {

        // 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;

        if (other instanceof CoordinatorImpl) {
            // For local Coordinator objects which are really instances of the
            // CoordinatorImpl class, get the global TID via a private
            // method call.
            if (other instanceof SubCoordinator) {
                otherTID = ((SubCoordinator)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.isSameTID(otherTID);
        }

        return false;
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish SubCoordinator.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.