AbstractService.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.apache.slide.common |
![]() |
![]() |
Jakarta Slide |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* $Header$
* $Revision: 207541 $
* $Date: 2004-07-28 05:48:34 -0400 (Wed, 28 Jul 2004) $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.common;
import java.util.Hashtable;
import java.util.Vector;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.slide.transaction.SlideTransactionManager;
/**
* Slide Service abstract implementation with support for multiple
* simultaneous transaction context.
*
* @version $Revision: 207541 $
*/
public abstract class AbstractService extends AbstractServiceBase
implements Service {
// -------------------------------------------------------------- Constants
public static final int TX_IDLE = 0;
public static final int TX_PREPARED = 1;
public static final int TX_SUSPENDED = 2;
// ----------------------------------------------------- Instance Variables
/**
* Current transaction context.
*/
protected Hashtable currentContexts = new Hashtable();
// ----------------------------------------------------- XAResource Mathods
/**
* Commit the global transaction specified by xid.
*
* @param xid A global transaction identifier
* @param onePhase If true, the resource manager should use a one-phase
* commit protocol to commit the work done on behalf of xid.
* @exception XAException An error has occurred. Possible XAExceptions
* are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
* XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO. If the resource
* manager did not commit the transaction and the paramether onePhase is
* set to true, the resource manager may throw one of the XA_RB*
* exceptions. Upon return, the resource manager has rolled back the
* branch's work and has released all held resources.
*/
public void commit(Xid xid, boolean onePhase)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_PROTO);
if (!onePhase && currentContextTuple.getStatus() != TX_PREPARED)
throw new XAException(XAException.XAER_PROTO);
if (onePhase &&
(!((currentContextTuple.getStatus() == TX_IDLE) ||
(currentContextTuple.getStatus() == TX_SUSPENDED))))
throw new XAException(XAException.XAER_PROTO);
if (((ContextTuple) currentContexts.get(Thread.currentThread()))
.getRollbackOnly()) {
rollback(xid);
throw new XAException(XAException.XA_RBROLLBACK);
}
currentContexts.remove(Thread.currentThread());
}
/**
* Ends the work performed on behalf of a transaction branch. The
* resource manager disassociates the XA resource from the transaction
* branch specified and let the transaction be completed.
* If TMSUSPEND is specified in flags, the transaction branch is
* temporarily suspended in incomplete state. The transaction context is
* in suspened state and must be resumed via start with TMRESUME specified.
* If TMFAIL is specified, the portion of work has failed. The resource
* manager may mark the transaction as rollback-only.
* If TMSUCCESS is specified, the portion of work has completed
* successfully.
*
* @param xid A global transaction identifier that is the same as what
* was used previously in the start method.
* @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND
* @exception XAException An error has occurred. Possible XAException
* values are XAER_RMERR, XAER_RMFAILED, XAER_NOTA, XAER_INVAL,
* XAER_PROTO, or XA_RB*.
*/
public void end(Xid xid, int flags)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_PROTO);
if (flags == XAResource.TMSUSPEND)
currentContextTuple.setStatus(TX_SUSPENDED);
if (flags == XAResource.TMFAIL)
((ContextTuple) currentContexts.get(Thread.currentThread()))
.setRollbackOnly(true);
}
/**
* Tell the resource manager to forget about a heuristically completed
* transaction branch.
*
* @param xid A global transaction identifier
* @exception XAException An error has occurred. Possible exception values
* are XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
*/
public void forget(Xid xid)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_PROTO);
currentContexts.remove(Thread.currentThread());
}
/**
* Obtain the current transaction timeout value set for this XAResource
* instance. If XAResource.setTransactionTimeout was not use prior to
* invoking this method, the return value is the default timeout set for
* the resource manager; otherwise, the value used in the previous
* setTransactionTimeout call is returned.
*
* @return the transaction timeout value in seconds.
* @exception XAException An error has occurred. Possible exception
* values are XAER_RMERR, XAER_RMFAIL.
*/
public int getTransactionTimeout()
throws XAException {
return ((ContextTuple) currentContexts.get(Thread.currentThread()))
.getTransactionTimeout();
}
/**
* This method is called to determine if the resource manager instance
* represented by the target object is the same as the resouce manager
* instance represented by the parameter xares.
*
* @param xares An XAResource object whose resource manager instance is
* to be compared with the resource manager instance of the target object.
* @return true if it's the same RM instance; otherwise false.
* @exception XAException An error has occurred. Possible exception values
* are XAER_RMERR, XAER_RMFAIL.
*/
public boolean isSameRM(XAResource xares)
throws XAException {
if (xares == null)
return false;
return (this == xares);
}
/**
* Ask the resource manager to prepare for a transaction commit of the
* transaction specified in xid.
*
* @param xid A global transaction identifier
* @return A value indicating the resource manager's vote on the outcome
* of the transaction. The possible values are: XA_RDONLY or XA_OK. If
* the resource manager wants to roll back the transaction, it should do
* so by raising an appropriate XAException in the prepare method.
* @exception XAException An error has occurred. Possible exception
* values are: XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL,
* or XAER_PROTO.
*/
public int prepare(Xid xid)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_PROTO);
if (!((currentContextTuple.getStatus() == TX_IDLE) ||
(currentContextTuple.getStatus() == TX_SUSPENDED)))
throw new XAException(XAException.XAER_PROTO);
if (((ContextTuple) currentContexts.get(Thread.currentThread()))
.getRollbackOnly()) {
// FIXME: Don't know if should be automatically rollbacked in that
// case
throw new XAException(XAException.XA_RBROLLBACK);
}
currentContextTuple.setStatus(TX_PREPARED);
return XAResource.XA_OK;
}
/**
* Obtain a list of prepared transaction branches from a resource manager.
* The transaction manager calls this method during recovery to obtain the
* list of transaction branches that are currently in prepared or
* heuristically completed states.
*
* @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMNOFLAGS must
* be used when no other flags are set in flags.
* @return The resource manager returns zero or more XIDs for the
* transaction branches that are currently in a prepared or heuristically
* completed state. If an error occurs during the operation, the resource
* manager should throw the appropriate XAException.
* @exception XAException An error has occurred. Possible values are
* XAER_RMERR, XAER_RMFAIL, XAER_INVAL, and XAER_PROTO.
*/
public Xid[] recover(int flag)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
Vector list = new Vector();
if ((currentContextTuple.getStatus() == TX_PREPARED) &&
(currentContext != null))
list.addElement(currentContext);
return (Xid[]) list.toArray(new Xid[list.size()]);
}
/**
* Inform the resource manager to roll back work done on behalf of a
* transaction branch.
*
* @param xid A global transaction identifier
* @exception XAException An error has occurred
*/
public void rollback(Xid xid)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_PROTO);
currentContexts.remove(Thread.currentThread());
}
/**
* Set the current transaction timeout value for this XAResource instance.
*
* @param seconds the transaction timeout value in seconds.
* @return true if transaction timeout value is set successfully;
* otherwise false.
* @exception XAException An error has occurred. Possible exception
* values are XAER_RMERR, XAER_RMFAIL, or XAER_INVAL.
*/
public boolean setTransactionTimeout(int seconds)
throws XAException {
((ContextTuple) currentContexts.get(Thread.currentThread()))
.setTransactionTimeout(seconds);
return true;
}
/**
* Start work on behalf of a transaction branch specified in xid If
* TMJOIN is specified, the start is for joining a transaction previously
* seen by the resource manager. If TMRESUME is specified, the start is
* to resume a suspended transaction specified in the parameter xid. If
* neither TMJOIN nor TMRESUME is specified and the transaction specified
* by xid has previously been seen by the resource manager, the resource
* manager throws the XAException exception with XAER_DUPID error code.
*
* @param xid A global transaction identifier to be associated with the
* resource
* @param flags One of TMNOFLAGS, TMJOIN, or TMRESUME
* @exception XAException An error has occurred. Possible exceptions are
* XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE, XAER_NOTA,
* XAER_INVAL, or XAER_PROTO.
*/
public void start(Xid xid, int flags)
throws XAException {
ContextTuple currentContextTuple =
(ContextTuple) currentContexts.get(Thread.currentThread());
Xid currentContext =
currentContextTuple!=null?currentContextTuple.getXid():null;
if (xid == null)
throw new XAException(XAException.XAER_INVAL);
if ( (currentContext != null) &&
(currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId()) )
throw new XAException(XAException.XAER_OUTSIDE);
switch (flags) {
case XAResource.TMNOFLAGS:
if (currentContext != null)
throw new XAException(XAException.XAER_INVAL);
currentContext = xid;
// is the idle status really ok ???
currentContexts.put
(Thread.currentThread(),new ContextTuple
(xid, TX_IDLE,
SlideTransactionManager.DEFAULT_TRANSACTION_TIMEOUT,
false));
break;
case XAResource.TMJOIN:
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (currentContext.getGlobalTransactionId()
!= xid.getGlobalTransactionId())
throw new XAException(XAException.XAER_INVAL);
break;
case XAResource.TMRESUME:
if (currentContext == null)
throw new XAException(XAException.XAER_NOTA);
if (currentContextTuple.getStatus() != TX_SUSPENDED)
throw new XAException(XAException.XAER_INVAL);
currentContextTuple.setStatus(TX_IDLE);
break;
}
}
// ------------------------------------------------ ContextTuple InnerClass
/**
* inner class to pack both the xid and the status
**/
private class ContextTuple {
private Xid xid;
private int status;
private int transactionTimeout;
private boolean rollbackOnly;
public ContextTuple(Xid xid, int status, int transactionTimeout,
boolean rollbackOnly) {
this.xid = xid;
setStatus(status);
setTransactionTimeout(transactionTimeout);
setRollbackOnly(rollbackOnly);
}
public Xid getXid() {
return xid;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getTransactionTimeout() {
return transactionTimeout;
}
public void setTransactionTimeout(int transactionTimeout) {
this.transactionTimeout = transactionTimeout;
}
public boolean getRollbackOnly() {
return rollbackOnly;
}
public void setRollbackOnly(boolean rollbackOnly) {
this.rollbackOnly = rollbackOnly;
}
}
}
The table below shows all metrics for AbstractService.java.




