All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arjuna.ServerTopLevelAction Maven / Gradle / Ivy

There is a newer version: 5.12.7.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags.
 * See the copyright.txt in the distribution for a full listing
 * of individual contributors.
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 *
 * (C) 2005-2006,
 * @author JBoss Inc.
 */
/*
 * Copyright (C) 1998, 1999, 2000, 2001,
 *
 * Hewlett Packard Arjuna Labs,
 * Newcastle upon Tyne,
 * Tyne and Wear,
 * UK.
 *
 * $Id: ServerTopLevelAction.java 2342 2006-03-30 13:06:17Z  $
 */

package com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arjuna;

import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INVALID_TRANSACTION;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
import org.omg.CORBA.UNKNOWN;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.HeuristicCommit;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicRollback;
import org.omg.CosTransactions.Inactive;
import org.omg.CosTransactions.NotPrepared;
import org.omg.CosTransactions.RecoveryCoordinator;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.Vote;

import com.arjuna.ats.arjuna.coordinator.ActionStatus;
import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.internal.arjuna.thread.ThreadActionData;
import com.arjuna.ats.internal.jts.ORBManager;
import com.arjuna.ats.internal.jts.interposition.resources.arjuna.Interposition;
import com.arjuna.ats.internal.jts.interposition.resources.arjuna.ServerResource;
import com.arjuna.ats.internal.jts.orbspecific.interposition.ServerControl;
import com.arjuna.ats.internal.jts.orbspecific.interposition.coordinator.ServerTransaction;
import com.arjuna.ats.jts.exceptions.ExceptionCodes;
import com.arjuna.ats.jts.logging.jtsLogger;

/**
 * This looks like an atomic action, but is not actually derived from
 * BasicAction or Transaction. This is because of the way in which the
 * OTS creates and manipulates transactions.
 *
 * As with Transaction, we only create actions here, and do not associated
 * these contexts with any thread. We do the association later.
 *
 * If we were to do the creation via a suitably modified current interface
 * then the thread association would be done for us automatically, and we
 * would not have to call resume at all.
 *
 * This is a top-level action proxy.
 */

/*
 * NOTE: all calls to pushAction in this and related classes are to do
 * with AIT abstract records. Some of them rely on being able to call
 * BasicAction.Current to determine what the current transaction is and
 * if we do not do thread-to-transaction association here then this all
 * breaks. There is no other reason for this. So, what we need to do
 * is remove this dependency by fixing the AIT records. This dependency
 * has a knock-on effect on certain optimisations we can make (e.g.,
 * local interpositon - see ServerControl.)
 */

public class ServerTopLevelAction extends ServerResource implements org.omg.CosTransactions.ResourceOperations
{

public ServerTopLevelAction (ServerControl control)
    {
	super(control);

	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::ServerTopLevelAction ( " + _theUid + " )");
    }

	_theResource = null;
	_resourceRef = getReference();

	/*
	 * Now attempt to do interposition registration.
	 */

	if (_resourceRef != null)
	{
	    /*
	     * Would like to be able to attach a thread filter
	     * to this object if process-filters aren't supported.
	     * However, currently this won't work as we can't have
	     * two different filter types working at the same
	     * time.
	     *
	     *		ATTACH_THREAD_FILTER_(_theResource);
	     */

	    Coordinator realCoordinator = _theControl.originalCoordinator();

	    if (!(_valid = registerResource(realCoordinator))) {

            /*
            * Failed to register. Valid is set, and the interposition
            * controller will now deal with this.
            */
        }

	    realCoordinator = null;
	}
	else
	    _valid = false;
    }

public Resource getReference ()
    {
	if ((_resourceRef == null) && _valid)
	{
	    if (_theControl != null)
	    {
		_theResource = new org.omg.CosTransactions.ResourcePOATie(this);

		ORBManager.getPOA().objectIsReady(_theResource);

		_resourceRef = org.omg.CosTransactions.ResourceHelper.narrow(ORBManager.getPOA().corbaReference(_theResource));
	    }
	    else
		_valid = false;
	}

	return _resourceRef;
    }

/*
 * Will only be called by the remote top-level transaction.
 */

public org.omg.CosTransactions.Vote prepare () throws HeuristicMixed, HeuristicHazard, SystemException
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::prepare for " + _theUid);
    }

	if (_theControl == null)
	{
	    throw new INVALID_TRANSACTION(ExceptionCodes.SERVERAA_NO_CONTROL, CompletionStatus.COMPLETED_NO);
	}

	if (_theControl.isWrapper())
	{
	    destroyResource();  // won't necessarily get another invocation!
	    return Vote.VoteReadOnly;
	}

	ServerTransaction theTransaction = (ServerTransaction) _theControl.getImplHandle();

	//ThreadActionData.pushAction(theTransaction); // LockManager needs to know if there is a transaction

	int result = TwoPhaseOutcome.PREPARE_NOTOK;

	/*
	 * Transaction may have locally timed out and been rolled back.
	 */

	int s = theTransaction.status();

	if ((s == ActionStatus.RUNNING) || (s == ActionStatus.ABORT_ONLY))
	    result = theTransaction.doPrepare();
	else
	{
	    switch (s)
	    {
	    case ActionStatus.COMMITTING:
	    case ActionStatus.COMMITTED:
	    case ActionStatus.H_COMMIT:
		result = TwoPhaseOutcome.PREPARE_OK;
		break;
	    case ActionStatus.H_MIXED:
		result = TwoPhaseOutcome.HEURISTIC_MIXED;
		break;
	    case ActionStatus.H_HAZARD:
		result = TwoPhaseOutcome.HEURISTIC_HAZARD;
		break;
	    }
	}

	ThreadActionData.popAction();

	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::prepare for " + _theUid + " : " + TwoPhaseOutcome.stringForm(result));
    }

	/*
	 * If prepare failed, then rollback now.
	 */

	if (result == TwoPhaseOutcome.PREPARE_NOTOK)
	{
	    try
	    {
		rollback();
	    }
	    catch (HeuristicCommit ex1)
	    {
		result = TwoPhaseOutcome.HEURISTIC_COMMIT;
	    }
	    catch (HeuristicMixed ex2)
	    {
		result = TwoPhaseOutcome.HEURISTIC_MIXED;
	    }
	    catch (HeuristicHazard ex3)
	    {
		result = TwoPhaseOutcome.HEURISTIC_HAZARD;
	    }
	    catch (SystemException ex4)
	    {
		result = TwoPhaseOutcome.HEURISTIC_HAZARD;
	    }
	}

	switch (result)
	{
	case TwoPhaseOutcome.INVALID_TRANSACTION:
	    throw new INVALID_TRANSACTION(ExceptionCodes.INVALID_ACTION, CompletionStatus.COMPLETED_NO);
	case TwoPhaseOutcome.PREPARE_OK:
	    return Vote.VoteCommit;
	case TwoPhaseOutcome.PREPARE_NOTOK:
	    destroyResource();  // won't necessarily get another invocation!

	    return Vote.VoteRollback;
	case TwoPhaseOutcome.PREPARE_READONLY:
	    destroyResource();  // won't necessarily get another invocation!

	    // what is we subsequently rollback?

	    return Vote.VoteReadOnly;
	case TwoPhaseOutcome.HEURISTIC_MIXED:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicMixed();  // will eventually get forget
	case TwoPhaseOutcome.HEURISTIC_HAZARD:
	default:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicHazard();
	}
    }

public void rollback () throws HeuristicCommit, HeuristicMixed, HeuristicHazard, SystemException
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::rollback for " + _theUid);
    }

	if (_theControl == null)
	{
	    throw new INVALID_TRANSACTION(ExceptionCodes.SERVERAA_NO_CONTROL, CompletionStatus.COMPLETED_NO);
	}

	if (_theControl.isWrapper())
	{
	    destroyResource();
	    return;
	}

	ServerTransaction theTransaction = (ServerTransaction) _theControl.getImplHandle();

	ThreadActionData.pushAction(theTransaction); // LockManager needs to know if there is a transaction

	int actionStatus = theTransaction.status();

	if (actionStatus == ActionStatus.PREPARED)
	{
	    /*
	     * This will also call any after_completions on
	     * registered synchronizations.
	     */

	    actionStatus = theTransaction.doPhase2Abort();
	}
	else
	{
	    if ((actionStatus == ActionStatus.RUNNING) ||
                (actionStatus == ActionStatus.ABORT_ONLY))
	    {
		try
		{
		    /*
		     * Have to do this because of the way PI works
		     * with thread-context association.
		     */

		    if (!valid())
			theTransaction.doPhase2Abort();  // must rollback
		    else
			theTransaction.rollback();

		    actionStatus = ActionStatus.ABORTED;
		}
		catch (SystemException ex)
		{
		    actionStatus = ActionStatus.ABORTED;

		    throw ex;
		}
		finally
		{
		    destroyResource();
		}
	    }
	}

	ThreadActionData.popAction();

	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::rollback for " + _theUid + " : " + ActionStatus.stringForm(actionStatus));
    }

	switch (actionStatus)
	{
	case ActionStatus.PREPARED:
	    throw new INVALID_TRANSACTION(ExceptionCodes.INVALID_ACTION, CompletionStatus.COMPLETED_NO);
	case ActionStatus.ABORTED:
	case ActionStatus.H_ROLLBACK:
	    destroyResource();
	    break;
	case ActionStatus.COMMITTED:
	case ActionStatus.H_COMMIT:
	    destroyResource();
	    throw new HeuristicCommit();
	case ActionStatus.H_MIXED:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicMixed();
	case ActionStatus.H_HAZARD:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicHazard();
	default:
	    destroyResource();
	    break;
	}
    }

public void commit () throws NotPrepared, HeuristicRollback, HeuristicMixed, HeuristicHazard, SystemException
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::commit for " + _theUid);
    }

	if (_theControl == null)
	{
	    throw new INVALID_TRANSACTION(ExceptionCodes.SERVERAA_NO_CONTROL, CompletionStatus.COMPLETED_NO);
	}

	if (_theControl.isWrapper())
	{
	    destroyResource();
	    return;
	}

	ServerTransaction theTransaction = (ServerTransaction) _theControl.getImplHandle();

	ThreadActionData.pushAction(theTransaction); // LockManager needs to know if there is a transaction

	int actionStatus = theTransaction.status();
	boolean notPrepared = false;

	if (actionStatus == ActionStatus.PREPARED)
	{
	    /*
	     * This will also call any after_completions on
	     * registered synchronizations.
	     */

	    actionStatus = theTransaction.doPhase2Commit();
	}
	else
	{
	    if (actionStatus == ActionStatus.RUNNING)
	    {
		if (jtsLogger.logger.isTraceEnabled()) {
            jtsLogger.logger.trace("ServerTopLevelAction::commit for " + _theUid + " : NotPrepared");
        }

		notPrepared = true;
	    }
	}

	ThreadActionData.popAction();

	if (notPrepared)
	    throw new NotPrepared();

	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::commit for " + _theUid + " : " + ActionStatus.stringForm(actionStatus));
    }

	switch (actionStatus)
	{
	case ActionStatus.PREPARED:
	    throw new INVALID_TRANSACTION(ExceptionCodes.SERVERAA_NO_CONTROL, CompletionStatus.COMPLETED_NO);
	case ActionStatus.COMMITTED:
	case ActionStatus.H_COMMIT:
	    destroyResource();
	    break;
	case ActionStatus.ABORTED:
	case ActionStatus.H_ROLLBACK:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicRollback();
	case ActionStatus.H_MIXED:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicMixed();
	case ActionStatus.H_HAZARD:
	    if (TxControl.getMaintainHeuristics())
		destroyResource();
	    throw new HeuristicHazard();
	default:
	    destroyResource();
	    break;
	}
    }

public void forget () throws SystemException
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::forget for " + _theUid);
    }

	boolean forgot = true;

	if (_theControl != null)
	    forgot = _theControl.forgetHeuristics();

	destroyResource();  // causes the removal of the transaction state.

	if (!forgot)
	    throw new BAD_OPERATION();
    }

public void commit_one_phase () throws HeuristicHazard, SystemException
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::commit_one_phase for " + _theUid);
    }

	if (_theControl == null)
	{
	    throw new INVALID_TRANSACTION(ExceptionCodes.SERVERAA_NO_CONTROL, CompletionStatus.COMPLETED_NO);
	}

	if (_theControl.isWrapper())
	{
	    destroyResource();
	    return;
	}

	ServerTransaction theTransaction = (ServerTransaction) _theControl.getImplHandle();

	if (theTransaction == null) {
        jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_notx("ServerTopLevelAction.commit_one_phase");

        throw new INVALID_TRANSACTION(ExceptionCodes.NO_TRANSACTION, CompletionStatus.COMPLETED_NO);
    }

	ThreadActionData.pushAction(theTransaction); // LockManager needs to know if there is a transaction

	try
	{
	    /*
	     * This will commit and do any before/after_completion calls
	     * on registered synchronizations.
	     */

	    theTransaction.doCommit(true);
	}
	catch (HeuristicHazard e1)
	{
	    /*
	     * Is a heuristic, then don't remove the
	     * transaction information.
	     */

	    ThreadActionData.popAction();

	    throw e1;
	}
	catch (TRANSACTION_ROLLEDBACK e4)
	{
	    ThreadActionData.popAction();

	    throw e4;
	}
	catch (INVALID_TRANSACTION e5)
	{
	    ThreadActionData.popAction();

	    throw e5;
	}
	catch (SystemException e6)
	{
	    ThreadActionData.popAction();

	    throw e6;
	}
	catch (Exception e7)
	{
	    ThreadActionData.popAction();

	    throw new UNKNOWN(e7.toString());
	}
	finally
	{
	    destroyResource();
	}

	ThreadActionData.popAction();

	destroyResource();
    }

public String type ()
    {
	return "/Resources/Arjuna/ServerTopLevelAction";
    }

protected ServerTopLevelAction ()
    {
	if (jtsLogger.logger.isTraceEnabled()) {
        jtsLogger.logger.trace("ServerTopLevelAction::ServerTopLevelAction ()");
    }

	_theResource = null;
	_resourceRef = null;
    }

protected synchronized void destroyResource ()
    {
	if (!_destroyed)
	{
	    try
	    {
		if (Interposition.destroy(get_uid()))
		    _destroyed = true;
	    }
	    catch (Exception e) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.destroyResource", e);
        }

	    try
	    {
		if (_theResource != null)
		{
		    ORBManager.getPOA().shutdownObject(_theResource);
		    _theResource = null;
		}
	    }
	    catch (Exception e) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.destroyResource", e);
        }
	}

	tidyup();
    }

protected boolean registerResource (Coordinator theCoordinator)
    {
	boolean result = false;

	if (theCoordinator != null)
	{
	    try
	    {
		/*
		 * Register resource and pass RecoveryCoordinator reference
		 * to the interposed transaction to save and restore.
		 */

		RecoveryCoordinator recoveryCoord = theCoordinator.register_resource(_resourceRef);

		if (!_theControl.isWrapper())
		{
		    ServerTransaction tx = (ServerTransaction) _theControl.getImplHandle();

		    if (tx != null)
		    {
			tx.setRecoveryCoordinator(recoveryCoord);

			result = true;
		    }
		    else {
			result = false;
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_ipfailed("ServerTopLevelAction");
		    }
		}
		else
		    result = true;
	    }
	    catch (ClassCastException classCastException) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.registerResource", classCastException);
        }
	    catch (Inactive ine) {
            jtsLogger.i18NLogger.warn_server_top_level_action_inactive();
            jtsLogger.i18NLogger.debug_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.registerResource", ine);
            transactionInactive = true;
        }
	    catch (TRANSACTION_ROLLEDBACK ex1) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.registerResource", ex1);
        }
	    catch (INVALID_TRANSACTION ex2) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.registerResource", ex2);
        }
	    catch (Exception e) {
            jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_generror("ServerTopLevelAction.registerResource", e);
        }
	}
	else {
        jtsLogger.i18NLogger.warn_orbspecific_interposition_resources_arjuna_nocoord("ServerTopLevelAction.registerResource");
    }

	return result;
    }

public boolean isTransactionInactive() {
    return transactionInactive;
}

protected org.omg.CosTransactions.ResourcePOATie _theResource;
protected Resource                               _resourceRef;
private boolean transactionInactive;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy