Author: manik.surtani(a)jboss.com
Date: 2008-04-28 06:17:51 -0400 (Mon, 28 Apr 2008)
New Revision: 5713
Added:
core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java
core/trunk/src/main/java/org/jboss/cache/transaction/GlobalTransactionContainer.java
Removed:
core/trunk/src/main/java/org/jboss/cache/invocation/CacheTransactionHelper.java
core/trunk/src/main/java/org/jboss/cache/invocation/InterceptorChain.java
core/trunk/src/main/java/org/jboss/cache/transaction/TxUtil.java
Modified:
core/trunk/src/main/java/org/jboss/cache/InvocationContext.java
core/trunk/src/main/java/org/jboss/cache/LifecycleManager.java
core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java
Log:
More refactoring and renaming
Modified: core/trunk/src/main/java/org/jboss/cache/InvocationContext.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/InvocationContext.java 2008-04-28 10:08:55
UTC (rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/InvocationContext.java 2008-04-28 10:17:51
UTC (rev 5713)
@@ -13,7 +13,7 @@
import org.jboss.cache.lock.NodeLock;
import org.jboss.cache.marshall.MethodCall;
import org.jboss.cache.transaction.GlobalTransaction;
-import org.jboss.cache.transaction.TxUtil;
+import org.jboss.cache.transaction.GlobalTransactionContainer;
import javax.transaction.Transaction;
import java.util.ArrayList;
@@ -452,7 +452,7 @@
public boolean isValidTransaction()
{
- return transaction != null && TxUtil.isValid(transaction);
+ return transaction != null &&
GlobalTransactionContainer.isValid(transaction);
}
public void throwIfNeeded(Throwable e) throws Throwable
Modified: core/trunk/src/main/java/org/jboss/cache/LifecycleManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/LifecycleManager.java 2008-04-28 10:08:55 UTC
(rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/LifecycleManager.java 2008-04-28 10:17:51 UTC
(rev 5713)
@@ -6,7 +6,7 @@
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.invocation.InterceptorChain;
+import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.invocation.NodeInvocationDelegate;
import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.lock.LockStrategyFactory;
Modified: core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-04-28 10:08:55 UTC
(rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-04-28 10:17:51 UTC
(rev 5713)
@@ -13,7 +13,7 @@
import org.jboss.cache.config.RuntimeConfig;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Stop;
-import org.jboss.cache.invocation.InterceptorChain;
+import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.lock.LockUtil;
import org.jboss.cache.lock.NodeLock;
Copied: core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java (from
rev 5712, core/trunk/src/main/java/org/jboss/cache/invocation/InterceptorChain.java)
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -0,0 +1,301 @@
+package org.jboss.cache.interceptors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.commands.VisitableCommand;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.interceptors.base.VisitorInterceptor;
+import org.jboss.cache.invocation.InvocationContextContainer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Knows how to build and manage an chain of interceptors. Also in charge with invoking
methods on the chain.
+ *
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+// TODO: Move to org.jboss.cache.interceptors
+public class InterceptorChain
+{
+ /**
+ * reference to the first interceptor in the chain
+ */
+ private VisitorInterceptor firstInChain;
+
+ /**
+ * used for invoking commands on the chain
+ */
+ private InvocationContextContainer invocationContextContainer;
+
+ private Log log = LogFactory.getLog(InterceptorChain.class);
+
+ /**
+ * Constructs an interceptor chain having the supplied interceptor as first.
+ */
+ public InterceptorChain(VisitorInterceptor first)
+ {
+ this.firstInChain = first;
+ }
+
+ @Inject
+ public void initialize(InvocationContextContainer invocationContextContainer)
+ {
+ this.invocationContextContainer = invocationContextContainer;
+ }
+
+ /**
+ * Inserts the given interceptor at the specified position in the chain (o based
indexing).
+ *
+ * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are
only 2 interceptors in the chain)
+ */
+ public synchronized void addInterceptor(VisitorInterceptor interceptor, int position)
+ {
+ if (position == 0)
+ {
+ interceptor.setNext(firstInChain);
+ firstInChain = interceptor;
+ return;
+ }
+ if (firstInChain == null) return;
+ VisitorInterceptor it = firstInChain;
+ int index = 0;
+ while (it != null)
+ {
+ if (++index == position)
+ {
+ interceptor.setNext(it.getNext());
+ it.setNext(interceptor);
+ return;
+ }
+ it = it.getNext();
+ }
+ throw new IllegalArgumentException("Invalid index: " + index + "
!");
+ }
+
+ /**
+ * Removes the interceptor at the given postion.
+ *
+ * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are
only 2 interceptors in the chain)
+ */
+ public synchronized void removeInterceptor(int position)
+ {
+ if (firstInChain == null) return;
+ if (position == 0)
+ {
+ firstInChain = firstInChain.getNext();
+ return;
+ }
+ VisitorInterceptor it = firstInChain;
+ int index = 0;
+ while (it != null)
+ {
+ if (++index == position)
+ {
+ if (it.getNext() == null) return; //nothing to remove
+ it.setNext(it.getNext().getNext());
+ return;
+ }
+ it = it.getNext();
+ }
+ throw new IllegalArgumentException("Invalid position: " + position +
" !");
+ }
+
+ /**
+ * Returns the number of interceptors in the chain.
+ */
+ public int size()
+ {
+ int size = 0;
+ VisitorInterceptor it = firstInChain;
+ while (it != null)
+ {
+ size++;
+ it = it.getNext();
+ }
+ return size;
+
+ }
+
+ /**
+ * Returns an unmofiable list with all the interceptors in sequence.
+ * If first in chain is null an empty list is returned.
+ */
+ public List<VisitorInterceptor> getInterceptorsAsList()
+ {
+ List<VisitorInterceptor> result;
+ if (firstInChain == null)
+ {
+ result = Collections.EMPTY_LIST;
+ }
+ List<VisitorInterceptor> retval = new
LinkedList<VisitorInterceptor>();
+ VisitorInterceptor tmp = firstInChain;
+ do
+ {
+ retval.add(tmp);
+ tmp = tmp.getNext();
+ }
+ while (tmp != null);
+ result = Collections.unmodifiableList(retval);
+ return result;
+ }
+
+
+ /**
+ * Removes all the occurences of supplied interceptor type from the chain.
+ */
+ public synchronized void removeInterceptor(Class<? extends VisitorInterceptor>
clazz)
+ {
+ if (firstInChain.getClass() == clazz)
+ {
+ firstInChain = firstInChain.getNext();
+ }
+ VisitorInterceptor it = firstInChain.getNext();
+ VisitorInterceptor prevIt = firstInChain;
+ while (it != null)
+ {
+ if (it.getClass() == clazz)
+ {
+ prevIt.setNext(it.getNext());
+ }
+ prevIt = it;
+ it = it.getNext();
+ }
+ }
+
+ /**
+ * Adds a new interceptor in list after an interceptor of a given type.
+ *
+ * @return true if the interceptor was added; i.e. the afterInterceptor exists
+ */
+ public synchronized boolean addInterceptor(VisitorInterceptor toAdd, Class<?
extends VisitorInterceptor> afterInterceptor)
+ {
+ VisitorInterceptor it = firstInChain;
+ while (it != null)
+ {
+ if (it.getClass().equals(afterInterceptor))
+ {
+ toAdd.setNext(it.getNext());
+ it.setNext(toAdd);
+ return true;
+ }
+ it = it.getNext();
+ }
+ return false;
+ }
+
+ /**
+ * Returns the chain as a list.
+ */
+ public List<VisitorInterceptor> asList()
+ {
+ List<VisitorInterceptor> result;
+ if (this.firstInChain == null)
+ {
+ result = null;
+ }
+ int num = 1;
+ VisitorInterceptor tmp = this.firstInChain;
+ while ((tmp = tmp.getNext()) != null)
+ {
+ num++;
+ }
+ List<VisitorInterceptor> retval = new
ArrayList<VisitorInterceptor>(num);
+ tmp = this.firstInChain;
+ num = 0;
+ do
+ {
+ retval.add(tmp);
+ tmp = tmp.getNext();
+ }
+ while (tmp != null);
+ result = retval;
+ return result;
+ }
+
+ /**
+ * Appends at the end.
+ */
+ public void appendIntereceptor(VisitorInterceptor ci)
+ {
+ VisitorInterceptor it = firstInChain;
+ while (it.hasNext()) it = it.getNext();
+ it.setNext(ci);
+ // make sure we nullify the "next" pointer in the last interceptor.
+ ci.setNext(null);
+ }
+
+ /**
+ * Walks the command through the interceptor chain. The received ctx is being passed
in.
+ */
+ @SuppressWarnings("deprecation")
+ public Object invoke(InvocationContext ctx, VisitableCommand command)
+ {
+ ctx.setCommand(command);
+ try
+ {
+ return command.acceptVisitor(ctx, firstInChain);
+ }
+ catch (CacheException e)
+ {
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Throwable t)
+ {
+ throw new CacheException(t);
+ }
+ }
+
+ /**
+ * Similar to {@link #invoke(org.jboss.cache.InvocationContext,
org.jboss.cache.commands.ReplicableCommand)}, but
+ * constructs a invocation context on the fly, using {@link
InvocationContextContainer#get()}
+ */
+ public Object invokeRemote(VisitableCommand cacheCommand) throws Throwable
+ {
+ InvocationContext ctxt = invocationContextContainer.get();
+ ctxt.setOriginLocal(false);
+ return cacheCommand.acceptVisitor(ctxt, firstInChain);
+ }
+
+ /**
+ * Similar to {@link #invoke(org.jboss.cache.InvocationContext,
org.jboss.cache.commands.ReplicableCommand)}, but
+ * constructs a invocation context on the fly, using {@link
InvocationContextContainer#get()} and setting the origin local flag to it's default
value.
+ */
+ public Object invoke(VisitableCommand cacheCommand) throws Throwable
+ {
+ InvocationContext ctxt = invocationContextContainer.get();
+ return cacheCommand.acceptVisitor(ctxt, firstInChain);
+ }
+
+ /**
+ * @return the first interceptor in the chain.
+ */
+ public VisitorInterceptor getFirstInChain()
+ {
+ return firstInChain;
+ }
+
+ /**
+ * Mainly used by unit tests to replace the interceptor chain with the starting point
passed in.
+ *
+ * @param interceptor interceptor to be used as the first interceptor in the chain.
+ */
+ public void setFirstInChain(VisitorInterceptor interceptor)
+ {
+ this.firstInChain = interceptor;
+ }
+
+ public InvocationContext getInvocationContext()
+ {
+ return invocationContextContainer.get();
+ }
+}
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2008-04-28
10:08:55 UTC (rev 5712)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -34,10 +34,10 @@
import org.jboss.cache.optimistic.TransactionWorkspace;
import org.jboss.cache.optimistic.WorkspaceNode;
import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.transaction.GlobalTransactionContainer;
import org.jboss.cache.transaction.OptimisticTransactionEntry;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
-import org.jboss.cache.transaction.TxUtil;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
@@ -230,7 +230,7 @@
if (!fqns.isEmpty())
{
// could be potentially TRANSACTIONAL. Ignore if it is, until we see a
prepare().
- if (tx == null || !TxUtil.isValid(tx))
+ if (tx == null || !GlobalTransactionContainer.isValid(tx))
{
// the no-tx case:
//replicate an evict call.
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java 2008-04-28
10:08:55 UTC (rev 5712)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -20,9 +20,8 @@
import org.jboss.cache.commands.write.RemoveNodeCommand;
import org.jboss.cache.config.Option;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.invocation.CacheTransactionHelper;
import org.jboss.cache.transaction.GlobalTransaction;
-import org.jboss.cache.transaction.TxUtil;
+import org.jboss.cache.transaction.GlobalTransactionContainer;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
@@ -34,11 +33,11 @@
*/
public class InvocationContextInterceptor extends BaseTransactionalContextInterceptor
implements InvocationContextInterceptorMBean
{
- private CacheTransactionHelper txHelper;
+ private GlobalTransactionContainer txHelper;
private RPCManager rpcManager;
@Inject
- public void setDependencies(CacheTransactionHelper cth, RPCManager rpcManager)
+ public void setDependencies(GlobalTransactionContainer cth, RPCManager rpcManager)
{
this.txHelper = cth;
this.rpcManager = rpcManager;
@@ -175,7 +174,7 @@
}
else
{
- if (ctx.getTransaction() != null &&
(TxUtil.isValid(ctx.getTransaction())))
+ if (ctx.getTransaction() != null &&
(GlobalTransactionContainer.isValid(ctx.getTransaction())))
{
copyInvocationScopeOptionsToTxScope(ctx);
}
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2008-04-28
10:08:55 UTC (rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -31,13 +31,12 @@
import org.jboss.cache.config.Option;
import org.jboss.cache.factories.CommandsFactory;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.invocation.CacheTransactionHelper;
import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.notifications.Notifier;
import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.transaction.GlobalTransactionContainer;
import org.jboss.cache.transaction.OptimisticTransactionEntry;
import org.jboss.cache.transaction.TransactionEntry;
-import org.jboss.cache.transaction.TxUtil;
import javax.transaction.InvalidTransactionException;
import javax.transaction.Status;
@@ -67,7 +66,7 @@
private Configuration configuration;
private CommandsFactory commandsFactory;
private RPCManager rpcManager;
- private CacheTransactionHelper transactionHelper;
+ private GlobalTransactionContainer transactionHelper;
private Notifier notifier;
private InvocationContextContainer invocationContextContainer;
private LifecycleManager lifecycleManager;
@@ -86,7 +85,7 @@
@Inject
public void intialize(Configuration configuration, RPCManager rpcManager,
- CacheTransactionHelper transactionHelper, Notifier notifier,
InvocationContextContainer icc,
+ GlobalTransactionContainer transactionHelper, Notifier notifier,
InvocationContextContainer icc,
LifecycleManager lifecycleManager, CommandsFactory factory)
{
this.configuration = configuration;
@@ -534,7 +533,7 @@
replayVisitorWithInject.visitCollection(ctx, command.getModifications());
retval = invokeNextInterceptor(ctx, command);
// JBCACHE-361 Confirm that the transaction is ACTIVE
- if (!TxUtil.isActive(ltx))
+ if (!GlobalTransactionContainer.isActive(ltx))
{
throw new ReplicationException("prepare() failed -- local transaction
status is not STATUS_ACTIVE;" +
" is " + ltx.getStatus());
@@ -711,7 +710,7 @@
private void assertTxIsActive(InvocationContext ctx)
throws SystemException
{
- if (!TxUtil.isActive(ctx.getTransaction()))
+ if (!GlobalTransactionContainer.isActive(ctx.getTransaction()))
{
throw new ReplicationException("prepare() failed -- " + "local
transaction status is not STATUS_ACTIVE; is " + ctx.getTransaction().getStatus());
}
@@ -981,7 +980,7 @@
private GlobalTransaction registerTransaction(Transaction tx, InvocationContext ctx)
throws Exception
{
GlobalTransaction gtx;
- if (TxUtil.isValid(tx) && transactions.put(tx, NULL) == null)
+ if (GlobalTransactionContainer.isValid(tx) && transactions.put(tx, NULL) ==
null)
{
gtx = transactionHelper.getCurrentTransaction(tx, true);
if (gtx.isRemote())
Deleted: core/trunk/src/main/java/org/jboss/cache/invocation/CacheTransactionHelper.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/invocation/CacheTransactionHelper.java 2008-04-28
10:08:55 UTC (rev 5712)
+++
core/trunk/src/main/java/org/jboss/cache/invocation/CacheTransactionHelper.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -1,194 +0,0 @@
-package org.jboss.cache.invocation;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.RPCManager;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.transaction.GlobalTransaction;
-import org.jboss.cache.transaction.OptimisticTransactionEntry;
-import org.jboss.cache.transaction.TransactionEntry;
-import org.jboss.cache.transaction.TransactionTable;
-import org.jgroups.Address;
-
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-/**
- * @author Mircea.Markus(a)jboss.com
- * @since 2.2
- */
-// TODO: Rename to GlobalTransactionFactory, and put in org.jboss.cache.transaction
-public class CacheTransactionHelper
-{
-
- private static final Log log = LogFactory.getLog(CacheTransactionHelper.class);
-
- /**
- * Maintains mapping of transactions (keys) and Modifications/Undo-Operations
- */
- private TransactionTable transactionTable;
-
- /**
- * Used to get the Transaction associated with the current thread
- */
- private TransactionManager transactionManager = null;
-
- private RPCManager rpcManager;
-
- private boolean isOptimisticLocking;
-
- @Inject
- public void initialize(TransactionTable transactionTable, TransactionManager
transactionManager,
- RPCManager rpcManager, Configuration configuration)
- {
- this.transactionTable = transactionTable;
- this.transactionManager = transactionManager;
- this.rpcManager = rpcManager;
- isOptimisticLocking = configuration.isNodeLockingOptimistic();
- }
-
- /**
- * Returns the transaction associated with the current thread.
- * If a local transaction exists, but doesn't yet have a mapping to a
- * GlobalTransaction, a new GlobalTransaction will be created and mapped to
- * the local transaction. Note that if a local transaction exists, but is
- * not ACTIVE or PREPARING, null is returned.
- *
- * @return A GlobalTransaction, or null if no (local) transaction was associated with
the current thread
- */
- public GlobalTransaction getCurrentTransaction()
- {
- return getCurrentTransaction(true);
- }
-
-
- /**
- * Returns the transaction associated with the thread; optionally creating
- * it if is does not exist.
- */
- public GlobalTransaction getCurrentTransaction(boolean createIfNotExists)
- {
- Transaction tx;
-
- if ((tx = getLocalTransaction()) == null)
- {// no transaction is associated with the current thread
- return null;
- }
-
- if (!isValid(tx))
- {// we got a non-null transaction, but it is not active anymore
- int status = -1;
- try
- {
- status = tx.getStatus();
- }
- catch (SystemException e)
- {
- }
-
- // JBCACHE-982 -- don't complain if COMMITTED
- if (status != Status.STATUS_COMMITTED)
- {
- log.warn("status is " + status + " (not ACTIVE or PREPARING);
returning null)", new Throwable());
- }
- else
- {
- log.trace("status is COMMITTED; returning null");
- }
-
- return null;
- }
-
- return getCurrentTransaction(tx, createIfNotExists);
- }
-
- /**
- * Returns the transaction associated with the current thread. We get the
- * initial context and a reference to the TransactionManager to get the
- * transaction. This method is used by {@link #getCurrentTransaction()}
- */
- protected Transaction getLocalTransaction()
- {
- if (transactionManager == null)
- {
- return null;
- }
- try
- {
- return transactionManager.getTransaction();
- }
- catch (Throwable t)
- {
- return null;
- }
- }
-
- /**
- * Returns true if transaction is ACTIVE or PREPARING, false otherwise.
- */
- private boolean isValid(Transaction tx)
- {
- if (tx == null) return false;
- int status;
- try
- {
- status = tx.getStatus();
- return status == Status.STATUS_ACTIVE || status == Status.STATUS_PREPARING;
- }
- catch (SystemException e)
- {
- log.error("failed getting transaction status", e);
- return false;
- }
- }
-
-
- /**
- * Returns the global transaction for this local transaction.
- */
- public GlobalTransaction getCurrentTransaction(Transaction tx)
- {
- return getCurrentTransaction(tx, true);
- }
-
- /**
- * Returns the global transaction for this local transaction.
- *
- * @param createIfNotExists if true, if a global transaction is not found; one is
created
- */
- public GlobalTransaction getCurrentTransaction(Transaction tx, boolean
createIfNotExists)
- {
- // removed synchronization on txTable because underlying implementation is thread
safe
- // and JTA spec (section 3.4.3 Thread of Control, par 2) says that only one thread
may
- // operate on the transaction at one time so no concern about 2 threads trying to
call
- // this method for the same Transaction instance at the same time
- //
- GlobalTransaction gtx = transactionTable.get(tx);
- if (gtx == null && createIfNotExists)
- {
- Address addr = rpcManager.getLocalAddress();
- gtx = GlobalTransaction.create(addr);
- transactionTable.put(tx, gtx);
- TransactionEntry ent = null;
- try
- {
- ent = isOptimisticLocking ? new OptimisticTransactionEntry(tx) : new
TransactionEntry(tx);
- }
- catch (Exception e)
- {
- throw new CacheException("Unable to create a transaction entry!",
e);
- }
-
- transactionTable.put(gtx, ent);
- if (log.isTraceEnabled())
- {
- log.trace("created new GTX: " + gtx + ", local TX=" +
tx);
- }
- }
- return gtx;
- }
-}
Deleted: core/trunk/src/main/java/org/jboss/cache/invocation/InterceptorChain.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/invocation/InterceptorChain.java 2008-04-28
10:08:55 UTC (rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/invocation/InterceptorChain.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -1,300 +0,0 @@
-package org.jboss.cache.invocation;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.commands.VisitableCommand;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.interceptors.base.VisitorInterceptor;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Knows how to build and manage an chain of interceptors. Also in charge with invoking
methods on the chain.
- *
- * @author Mircea.Markus(a)jboss.com
- * @since 2.2
- */
-// TODO: Move to org.jboss.cache.interceptors
-public class InterceptorChain
-{
- /**
- * reference to the first interceptor in the chain
- */
- private VisitorInterceptor firstInChain;
-
- /**
- * used for invoking commands on the chain
- */
- private InvocationContextContainer invocationContextContainer;
-
- private Log log = LogFactory.getLog(InterceptorChain.class);
-
- /**
- * Constructs an interceptor chain having the supplied interceptor as first.
- */
- public InterceptorChain(VisitorInterceptor first)
- {
- this.firstInChain = first;
- }
-
- @Inject
- public void initialize(InvocationContextContainer invocationContextContainer)
- {
- this.invocationContextContainer = invocationContextContainer;
- }
-
- /**
- * Inserts the given interceptor at the specified position in the chain (o based
indexing).
- *
- * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are
only 2 interceptors in the chain)
- */
- public synchronized void addInterceptor(VisitorInterceptor interceptor, int position)
- {
- if (position == 0)
- {
- interceptor.setNext(firstInChain);
- firstInChain = interceptor;
- return;
- }
- if (firstInChain == null) return;
- VisitorInterceptor it = firstInChain;
- int index = 0;
- while (it != null)
- {
- if (++index == position)
- {
- interceptor.setNext(it.getNext());
- it.setNext(interceptor);
- return;
- }
- it = it.getNext();
- }
- throw new IllegalArgumentException("Invalid index: " + index + "
!");
- }
-
- /**
- * Removes the interceptor at the given postion.
- *
- * @throws IllegalArgumentException if the position is invalid (e.g. 5 and there are
only 2 interceptors in the chain)
- */
- public synchronized void removeInterceptor(int position)
- {
- if (firstInChain == null) return;
- if (position == 0)
- {
- firstInChain = firstInChain.getNext();
- return;
- }
- VisitorInterceptor it = firstInChain;
- int index = 0;
- while (it != null)
- {
- if (++index == position)
- {
- if (it.getNext() == null) return; //nothing to remove
- it.setNext(it.getNext().getNext());
- return;
- }
- it = it.getNext();
- }
- throw new IllegalArgumentException("Invalid position: " + position +
" !");
- }
-
- /**
- * Returns the number of interceptors in the chain.
- */
- public int size()
- {
- int size = 0;
- VisitorInterceptor it = firstInChain;
- while (it != null)
- {
- size++;
- it = it.getNext();
- }
- return size;
-
- }
-
- /**
- * Returns an unmofiable list with all the interceptors in sequence.
- * If first in chain is null an empty list is returned.
- */
- public List<VisitorInterceptor> getInterceptorsAsList()
- {
- List<VisitorInterceptor> result;
- if (firstInChain == null)
- {
- result = Collections.EMPTY_LIST;
- }
- List<VisitorInterceptor> retval = new
LinkedList<VisitorInterceptor>();
- VisitorInterceptor tmp = firstInChain;
- do
- {
- retval.add(tmp);
- tmp = tmp.getNext();
- }
- while (tmp != null);
- result = Collections.unmodifiableList(retval);
- return result;
- }
-
-
- /**
- * Removes all the occurences of supplied interceptor type from the chain.
- */
- public synchronized void removeInterceptor(Class<? extends VisitorInterceptor>
clazz)
- {
- if (firstInChain.getClass() == clazz)
- {
- firstInChain = firstInChain.getNext();
- }
- VisitorInterceptor it = firstInChain.getNext();
- VisitorInterceptor prevIt = firstInChain;
- while (it != null)
- {
- if (it.getClass() == clazz)
- {
- prevIt.setNext(it.getNext());
- }
- prevIt = it;
- it = it.getNext();
- }
- }
-
- /**
- * Adds a new interceptor in list after an interceptor of a given type.
- *
- * @return true if the interceptor was added; i.e. the afterInterceptor exists
- */
- public synchronized boolean addInterceptor(VisitorInterceptor toAdd, Class<?
extends VisitorInterceptor> afterInterceptor)
- {
- VisitorInterceptor it = firstInChain;
- while (it != null)
- {
- if (it.getClass().equals(afterInterceptor))
- {
- toAdd.setNext(it.getNext());
- it.setNext(toAdd);
- return true;
- }
- it = it.getNext();
- }
- return false;
- }
-
- /**
- * Returns the chain as a list.
- */
- public List<VisitorInterceptor> asList()
- {
- List<VisitorInterceptor> result;
- if (this.firstInChain == null)
- {
- result = null;
- }
- int num = 1;
- VisitorInterceptor tmp = this.firstInChain;
- while ((tmp = tmp.getNext()) != null)
- {
- num++;
- }
- List<VisitorInterceptor> retval = new
ArrayList<VisitorInterceptor>(num);
- tmp = this.firstInChain;
- num = 0;
- do
- {
- retval.add(tmp);
- tmp = tmp.getNext();
- }
- while (tmp != null);
- result = retval;
- return result;
- }
-
- /**
- * Appends at the end.
- */
- public void appendIntereceptor(VisitorInterceptor ci)
- {
- VisitorInterceptor it = firstInChain;
- while (it.hasNext()) it = it.getNext();
- it.setNext(ci);
- // make sure we nullify the "next" pointer in the last interceptor.
- ci.setNext(null);
- }
-
- /**
- * Walks the command through the interceptor chain. The received ctx is being passed
in.
- */
- @SuppressWarnings("deprecation")
- public Object invoke(InvocationContext ctx, VisitableCommand command)
- {
- ctx.setCommand(command);
- try
- {
- return command.acceptVisitor(ctx, firstInChain);
- }
- catch (CacheException e)
- {
- throw e;
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Throwable t)
- {
- throw new CacheException(t);
- }
- }
-
- /**
- * Similar to {@link #invoke(org.jboss.cache.InvocationContext,
org.jboss.cache.commands.ReplicableCommand)}, but
- * constructs a invocation context on the fly, using {@link
InvocationContextContainer#get()}
- */
- public Object invokeRemote(VisitableCommand cacheCommand) throws Throwable
- {
- InvocationContext ctxt = invocationContextContainer.get();
- ctxt.setOriginLocal(false);
- return cacheCommand.acceptVisitor(ctxt, firstInChain);
- }
-
- /**
- * Similar to {@link #invoke(org.jboss.cache.InvocationContext,
org.jboss.cache.commands.ReplicableCommand)}, but
- * constructs a invocation context on the fly, using {@link
InvocationContextContainer#get()} and setting the origin local flag to it's default
value.
- */
- public Object invoke(VisitableCommand cacheCommand) throws Throwable
- {
- InvocationContext ctxt = invocationContextContainer.get();
- return cacheCommand.acceptVisitor(ctxt, firstInChain);
- }
-
- /**
- * @return the first interceptor in the chain.
- */
- public VisitorInterceptor getFirstInChain()
- {
- return firstInChain;
- }
-
- /**
- * Mainly used by unit tests to replace the interceptor chain with the starting point
passed in.
- *
- * @param interceptor interceptor to be used as the first interceptor in the chain.
- */
- public void setFirstInChain(VisitorInterceptor interceptor)
- {
- this.firstInChain = interceptor;
- }
-
- public InvocationContext getInvocationContext()
- {
- return invocationContextContainer.get();
- }
-}
Modified: core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java 2008-04-28 10:08:55 UTC
(rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/lock/LockManager.java 2008-04-28 10:17:51 UTC
(rev 5713)
@@ -11,9 +11,9 @@
import org.jboss.cache.factories.CommandsFactory;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.transaction.GlobalTransactionContainer;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
-import org.jboss.cache.transaction.TxUtil;
import java.util.HashMap;
import java.util.List;
@@ -98,7 +98,7 @@
// if the tx associated with the current thread is rolling back, barf! JBCACHE-923
if (gtx != null)
{
- TxUtil.assertTransactionValid(ctx);
+ GlobalTransactionContainer.assertTransactionValid(ctx);
}
Object owner = (gtx != null) ? gtx : currentThread;
NodeSPI currentNode;
Copied:
core/trunk/src/main/java/org/jboss/cache/transaction/GlobalTransactionContainer.java (from
rev 5706,
core/trunk/src/main/java/org/jboss/cache/invocation/CacheTransactionHelper.java)
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/transaction/GlobalTransactionContainer.java
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/transaction/GlobalTransactionContainer.java 2008-04-28
10:17:51 UTC (rev 5713)
@@ -0,0 +1,234 @@
+package org.jboss.cache.transaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.RPCManager;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jgroups.Address;
+
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ * @since 2.2
+ */
+public class GlobalTransactionContainer
+{
+
+ private static final Log log = LogFactory.getLog(GlobalTransactionContainer.class);
+
+ /**
+ * Maintains mapping of transactions (keys) and Modifications/Undo-Operations
+ */
+ private TransactionTable transactionTable;
+
+ /**
+ * Used to get the Transaction associated with the current thread
+ */
+ private TransactionManager transactionManager = null;
+
+ private RPCManager rpcManager;
+
+ private boolean isOptimisticLocking;
+
+ @Inject
+ public void initialize(TransactionTable transactionTable, TransactionManager
transactionManager,
+ RPCManager rpcManager, Configuration configuration)
+ {
+ this.transactionTable = transactionTable;
+ this.transactionManager = transactionManager;
+ this.rpcManager = rpcManager;
+ isOptimisticLocking = configuration.isNodeLockingOptimistic();
+ }
+
+ /**
+ * Returns the transaction associated with the current thread.
+ * If a local transaction exists, but doesn't yet have a mapping to a
+ * GlobalTransaction, a new GlobalTransaction will be created and mapped to
+ * the local transaction. Note that if a local transaction exists, but is
+ * not ACTIVE or PREPARING, null is returned.
+ *
+ * @return A GlobalTransaction, or null if no (local) transaction was associated with
the current thread
+ */
+ public GlobalTransaction getCurrentTransaction()
+ {
+ return getCurrentTransaction(true);
+ }
+
+
+ /**
+ * Returns the transaction associated with the thread; optionally creating
+ * it if is does not exist.
+ */
+ public GlobalTransaction getCurrentTransaction(boolean createIfNotExists)
+ {
+ Transaction tx;
+
+ if ((tx = getLocalTransaction()) == null)
+ {// no transaction is associated with the current thread
+ return null;
+ }
+
+ if (!isValid(tx))
+ {// we got a non-null transaction, but it is not active anymore
+ int status = -1;
+ try
+ {
+ status = tx.getStatus();
+ }
+ catch (SystemException e)
+ {
+ }
+
+ // JBCACHE-982 -- don't complain if COMMITTED
+ if (status != Status.STATUS_COMMITTED)
+ {
+ log.warn("status is " + status + " (not ACTIVE or PREPARING);
returning null)");
+ }
+ else
+ {
+ log.trace("status is COMMITTED; returning null");
+ }
+
+ return null;
+ }
+
+ return getCurrentTransaction(tx, createIfNotExists);
+ }
+
+ /**
+ * Returns the transaction associated with the current thread. We get the
+ * initial context and a reference to the TransactionManager to get the
+ * transaction. This method is used by {@link #getCurrentTransaction()}
+ */
+ protected Transaction getLocalTransaction()
+ {
+ if (transactionManager == null)
+ {
+ return null;
+ }
+ try
+ {
+ return transactionManager.getTransaction();
+ }
+ catch (Throwable t)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns true if transaction is ACTIVE, false otherwise
+ */
+ public static boolean isActive(Transaction tx)
+ {
+ if (tx == null) return false;
+ int status = -1;
+ try
+ {
+ status = tx.getStatus();
+ return status == Status.STATUS_ACTIVE;
+ }
+ catch (SystemException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if transaction is PREPARING, false otherwise
+ */
+ public static boolean isPreparing(Transaction tx)
+ {
+ if (tx == null) return false;
+ int status = -1;
+ try
+ {
+ status = tx.getStatus();
+ return status == Status.STATUS_PREPARING;
+ }
+ catch (SystemException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Return s true of tx's status is ACTIVE or PREPARING
+ *
+ * @param tx
+ * @return true if the tx is active or preparing
+ */
+ public static boolean isValid(Transaction tx)
+ {
+ return isActive(tx) || isPreparing(tx);
+ }
+
+ /**
+ * Tests whether the caller is in a valid transaction. If not, will throw a
CacheException.
+ */
+ public static void assertTransactionValid(InvocationContext ctx)
+ {
+ Transaction tx = ctx.getTransaction();
+ if (!isValid(tx)) try
+ {
+ throw new CacheException("Invalid transaction " + tx + ", status
= " + (tx == null ? null : tx.getStatus()));
+ }
+ catch (SystemException e)
+ {
+ throw new CacheException("Exception trying to analyse status of transaction
" + tx, e);
+ }
+ }
+
+
+ /**
+ * Returns the global transaction for this local transaction.
+ */
+ public GlobalTransaction getCurrentTransaction(Transaction tx)
+ {
+ return getCurrentTransaction(tx, true);
+ }
+
+ /**
+ * Returns the global transaction for this local transaction.
+ *
+ * @param createIfNotExists if true, if a global transaction is not found; one is
created
+ */
+ public GlobalTransaction getCurrentTransaction(Transaction tx, boolean
createIfNotExists)
+ {
+ // removed synchronization on txTable because underlying implementation is thread
safe
+ // and JTA spec (section 3.4.3 Thread of Control, par 2) says that only one thread
may
+ // operate on the transaction at one time so no concern about 2 threads trying to
call
+ // this method for the same Transaction instance at the same time
+ //
+ GlobalTransaction gtx = transactionTable.get(tx);
+ if (gtx == null && createIfNotExists)
+ {
+ Address addr = rpcManager.getLocalAddress();
+ gtx = GlobalTransaction.create(addr);
+ transactionTable.put(tx, gtx);
+ TransactionEntry ent = null;
+ try
+ {
+ ent = isOptimisticLocking ? new OptimisticTransactionEntry(tx) : new
TransactionEntry(tx);
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create a transaction entry!",
e);
+ }
+
+ transactionTable.put(gtx, ent);
+ if (log.isTraceEnabled())
+ {
+ log.trace("created new GTX: " + gtx + ", local TX=" +
tx);
+ }
+ }
+ return gtx;
+ }
+}
Deleted: core/trunk/src/main/java/org/jboss/cache/transaction/TxUtil.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/transaction/TxUtil.java 2008-04-28 10:08:55
UTC (rev 5712)
+++ core/trunk/src/main/java/org/jboss/cache/transaction/TxUtil.java 2008-04-28 10:17:51
UTC (rev 5713)
@@ -1,81 +0,0 @@
-package org.jboss.cache.transaction;
-
-import org.jboss.cache.CacheException;
-import org.jboss.cache.InvocationContext;
-
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-
-/**
- * @author Mircea.Markus(a)jboss.com
- * @since 2.2
- */
-// TODO: Can this stuff be moved into CacheTransactionHelper ?
-public class TxUtil
-{
- /**
- * Returns true if transaction is ACTIVE, false otherwise
- */
- public static boolean isActive(Transaction tx)
- {
- if (tx == null) return false;
- int status = -1;
- try
- {
- status = tx.getStatus();
- return status == Status.STATUS_ACTIVE;
- }
- catch (SystemException e)
- {
-// log.error("failed getting transaction status", e);
- return false;
- }
- }
-
- /**
- * Returns true if transaction is PREPARING, false otherwise
- */
- public static boolean isPreparing(Transaction tx)
- {
- if (tx == null) return false;
- int status = -1;
- try
- {
- status = tx.getStatus();
- return status == Status.STATUS_PREPARING;
- }
- catch (SystemException e)
- {
-// log.error("failed getting transaction status", e);
- return false;
- }
- }
-
- /**
- * Return s true of tx's status is ACTIVE or PREPARING
- *
- * @param tx
- * @return true if the tx is active or preparing
- */
- public static boolean isValid(Transaction tx)
- {
- return isActive(tx) || isPreparing(tx);
- }
-
- /**
- * Tests whether the caller is in a valid transaction. If not, will throw a
CacheException.
- */
- public static void assertTransactionValid(InvocationContext ctx)
- {
- Transaction tx = ctx.getTransaction();
- if (!isValid(tx)) try
- {
- throw new CacheException("Invalid transaction " + tx + ", status
= " + (tx == null ? null : tx.getStatus()));
- }
- catch (SystemException e)
- {
- throw new CacheException("Exception trying to analyse status of transaction
" + tx, e);
- }
- }
-}