/*
* 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) 2001, 2002,
*
* Hewlett-Packard Arjuna Labs,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: ServerControl.java 2342 2006-03-30 13:06:17Z $
*/
package com.arjuna.ats.internal.jts.orbspecific.interposition;
import java.util.Hashtable;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.SystemException;
import org.omg.CosTransactions.Control;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.Terminator;
import com.arjuna.ArjunaOTS.ActiveThreads;
import com.arjuna.ArjunaOTS.ActiveTransaction;
import com.arjuna.ArjunaOTS.BadControl;
import com.arjuna.ArjunaOTS.Destroyed;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.coordinator.BasicAction;
import com.arjuna.ats.internal.jts.orbspecific.ControlImple;
import com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple;
import com.arjuna.ats.internal.jts.orbspecific.interposition.coordinator.ServerTransaction;
import com.arjuna.ats.jts.logging.jtsLogger;
/**
* As with ControlImple, the transaction is maintained until the control object
* is deleted.
*
* This class maintains a handle on the current server-side transaction, and
* also references to the original transaction it is "mirroring". This allows us
* to have a single place to hold both sets of information which is accessible
* to interposed resources, synchronizations, and transactions.
*
* @author Mark Little (mark@arjuna.com)
* @version $Id: ServerControl.java 2342 2006-03-30 13:06:17Z $
* @since JTS 1.0.
*/
public class ServerControl extends ControlImple
{
public ServerControl (Uid actUid, Control parentCon, ArjunaTransactionImple parentTran, Coordinator realCoord, Terminator realTerm)
{
super();
_realCoordinator = realCoord;
_realTerminator = realTerm;
_parentControl = parentCon;
/*
* allControls only contains local controls. Have we seen this
* transaction before, i.e., is it a locally created transaction that we
* are re-importing?
*/
ControlImple cont = ((ControlImple.allControls != null) ? (ControlImple) ControlImple.allControls.get(actUid)
: null);
/*
* We could do optimisations based on whether this is a transaction we
* have locally created anyway and somehow it is being re-imported. If
* that is the case, then why create a new transaction to manage it -
* this will only add to the disk access? However, currently we cannot
* do this optimisation because:
*
* (i) if the original control is being terminated from a remote
* process, it will not be able to force thread-to-transaction
* association (ArjunaTransactionImple et al don't do that.)
*
* (ii) certain AIT records require thread-to-transaction association in
* order to work (e.g., LockRecord).
*
* What this means is that if we do this optimisation and an application
* uses AIT, all AIT records will be added to the parent (original)
* transaction and not the interposed transaction (which does do
* thread-to-transaction association - or the resource does). Then when
* the transaction is terminated, these records will be processed and
* they will not be able to determine the current transaction.
*/
if (cont != null)
{
_isWrapper = true;
_transactionHandle = cont.getImplHandle();
Coordinator coord = null;
Terminator term = null;
try
{
coord = cont.get_coordinator();
term = cont.get_terminator();
}
catch (Exception e)
{
e.printStackTrace();
try
{
if (coord != null)
coord.rollback_only();
}
catch (Exception ex)
{
}
}
super.duplicateTransactionHandle(coord, term);
}
else
{
_transactionHandle = new ServerTransaction(actUid, _parentControl,
parentTran);
_isWrapper = false;
super.createTransactionHandle();
/*
* Pass a pointer to the control to the transaction so it knows what
* the control is. We use this for transaction comparison and
* thread-to-context management.
*/
_transactionHandle.setControlHandle(this);
}
_theUid = _transactionHandle.get_uid();
addControl();
}
public final boolean isWrapper ()
{
return _isWrapper;
}
public Coordinator originalCoordinator ()
{
return _realCoordinator;
}
public Terminator originalTerminator ()
{
return _realTerminator;
}
public synchronized void destroy () throws ActiveTransaction,
ActiveThreads, BadControl, Destroyed, SystemException
{
if (super._destroyed)
throw new Destroyed();
/*
* We are about to delete ourself (!) so make sure we don't using
* anything on the stack after this point. This includes returning
* variables.
*/
try
{
if (_isWrapper)
{
_transactionHandle = null;
}
super.destroy();
}
catch (BAD_PARAM e)
{
// already destroyed
}
catch (Destroyed de)
{
// already destroyed
}
catch (Exception e) {
jtsLogger.i18NLogger.warn_orbspecific_interposition_destfailed("ServerControl", e);
}
}
public ServerControl (ServerTransaction stx)
{
super();
_realCoordinator = null;
_realTerminator = null;
_isWrapper = false;
_transactionHandle = stx;
_theUid = stx.get_uid();
_transactionHandle.setControlHandle(this); // JBTM-957
createTransactionHandle();
addControl();
}
public ControlImple getParentImple ()
{
BasicAction parent = _transactionHandle.parent();
if (parent != null)
{
synchronized (ServerControl.allControls)
{
return (ControlImple) ServerControl.allServerControls.get(parent.get_uid());
}
}
else
return null;
}
public String toString ()
{
return "ServerControl < " + get_uid() + " >";
}
public final boolean forgetHeuristics ()
{
if (_transactionHandle != null)
return _transactionHandle.forgetHeuristics();
else
return true;
}
protected boolean addControl ()
{
synchronized (ServerControl.allServerControls)
{
ServerControl.allServerControls.put(get_uid(), this);
}
return true;
}
protected boolean removeControl ()
{
try
{
synchronized (ServerControl.allServerControls)
{
ServerControl.allServerControls.remove(get_uid());
}
}
catch (Exception ex)
{
return false;
}
return true;
}
/*
* Make private, with public accessor.
*/
public static Hashtable allServerControls = new Hashtable();
private Coordinator _realCoordinator;
private Terminator _realTerminator;
private boolean _isWrapper;
}