[jboss-cvs] JBossCache/src/org/jboss/cache/interceptors ...
Manik Surtani
msurtani at jboss.com
Wed Sep 6 13:58:20 EDT 2006
User: msurtani
Date: 06/09/06 13:58:20
Modified: src/org/jboss/cache/interceptors
InvocationContextInterceptor.java
TxInterceptor.java
Added: src/org/jboss/cache/interceptors
BaseTransactionalContextInterceptor.java
Log:
Refactored tx interceptor so the invocation context interceptor sets up the context initially. Also fixed some breakage in PojoTreeCache
Revision Changes Path
1.3 +92 -3 JBossCache/src/org/jboss/cache/interceptors/InvocationContextInterceptor.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: InvocationContextInterceptor.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/interceptors/InvocationContextInterceptor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- InvocationContextInterceptor.java 5 Sep 2006 18:09:56 -0000 1.2
+++ InvocationContextInterceptor.java 6 Sep 2006 17:58:20 -0000 1.3
@@ -6,20 +6,50 @@
*/
package org.jboss.cache.interceptors;
+import org.jboss.cache.GlobalTransaction;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.config.Option;
import org.jboss.cache.marshall.MethodCall;
+import org.jboss.cache.marshall.MethodDeclarations;
+
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
/**
* Always place this interceptor at the start of the interceptor chain to ensure invocation contexts and set up and cleaned up correctly.
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
*/
-public class InvocationContextInterceptor extends Interceptor implements InvocationContextInterceptorMBean
+public class InvocationContextInterceptor extends BaseTransactionalContextInterceptor implements InvocationContextInterceptorMBean
{
public Object invoke(MethodCall call) throws Throwable
{
+ InvocationContext ctx = cache.getInvocationContext();
+ Option optionOverride = ctx.getOptionOverrides();
+ Transaction suspendedTransaction = null;
+ boolean resumeSuspended = false;
+
try
{
- if (cache.getInvocationContext().getOptionOverrides().isBypassInterceptorChain())
+ setTransactionalContext(getTransaction(), getGlobalTransaction(call));
+
+ if (optionOverride != null && optionOverride.isFailSilently())
+ {
+ log.debug("FAIL_SILENTLY Option is present - suspending any ongoing transaction.");
+ if (ctx.getTransaction() != null)
+ {
+ suspendedTransaction = txManager.suspend();
+ if (log.isTraceEnabled()) log.trace("Suspending transaction " + suspendedTransaction);
+ resumeSuspended = true;
+ }
+ else
+ {
+ log.trace("No ongoing transaction to suspend");
+ }
+ }
+
+
+ if (optionOverride.isBypassInterceptorChain())
{
return getLast().invoke(call);
}
@@ -31,7 +61,66 @@
finally
{
// clean up any invocation-scope options set up
- cache.getInvocationContext().getOptionOverrides().reset();
+ optionOverride.reset();
+
+ if (resumeSuspended)
+ {
+ txManager.resume(suspendedTransaction);
}
+ else
+ {
+ if (ctx.getTransaction() != null && isValid(ctx.getTransaction()))
+ {
+ copyInvocationScopeOptionsToTxScope(ctx);
+ }
+ }
+ }
+ }
+
+ private GlobalTransaction getGlobalTransaction(MethodCall call)
+ {
+ GlobalTransaction gtx = null;
+ if (MethodDeclarations.isTransactionLifecycleMethod(call.getMethodId()))
+ {
+ gtx = findGlobalTransaction(call.getArgs());
+ gtx.setRemote(isRemoteGlobalTx(gtx));
+ }
+ return gtx;
+ }
+
+ private Transaction getTransaction() throws SystemException
+ {
+ // this creates a context if one did not exist.
+ if (txManager == null)
+ {
+ log.trace("no transaction manager configured, setting tx as null.");
+ return null;
+ }
+ else
+ {
+ return txManager.getTransaction();
+ }
+ }
+
+ protected GlobalTransaction findGlobalTransaction(Object[] params)
+ {
+ int clue = 0;
+
+ if (params[clue] instanceof GlobalTransaction)
+ return (GlobalTransaction) params[clue];
+ else
+ for (Object param : params) if (param instanceof GlobalTransaction) return (GlobalTransaction) param;
+ return null;
+ }
+
+ /**
+ * Tests if a global transaction originated from a different cache in the cluster
+ *
+ * @param gtx
+ * @return true if the gtx is remote, false if it originated locally.
+ */
+ private boolean isRemoteGlobalTx(GlobalTransaction gtx)
+ {
+ return gtx != null && (gtx.getAddress() != null) && (!gtx.getAddress().equals(cache.getLocalAddress()));
}
}
1.60 +19 -110 JBossCache/src/org/jboss/cache/interceptors/TxInterceptor.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: TxInterceptor.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/interceptors/TxInterceptor.java,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -b -r1.59 -r1.60
--- TxInterceptor.java 5 Sep 2006 18:09:56 -0000 1.59
+++ TxInterceptor.java 6 Sep 2006 17:58:20 -0000 1.60
@@ -14,7 +14,6 @@
import org.jboss.cache.OptimisticTransactionEntry;
import org.jboss.cache.ReplicationException;
import org.jboss.cache.TransactionEntry;
-import org.jboss.cache.TransactionTable;
import org.jboss.cache.TreeCacheProxyImpl;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Option;
@@ -27,9 +26,7 @@
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -42,7 +39,7 @@
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
* @author <a href="mailto:stevew at jofti.com">Steve Woodcock (stevew at jofti.com)</a>
*/
-public class TxInterceptor extends Interceptor implements TxInterceptorMBean
+public class TxInterceptor extends BaseTransactionalContextInterceptor implements TxInterceptorMBean
{
/**
* List <Transaction>that we have registered for
@@ -53,9 +50,6 @@
private long m_commits = 0;
private long m_rollbacks = 0;
final static Object NULL = new Object();
- protected TransactionManager txManager = null;
- protected TransactionTable txTable = null;
-
/**
* Set<GlobalTransaction> of GlobalTransactions that originated somewhere else (we didn't create them).
@@ -64,14 +58,6 @@
*/
private Map remoteTransactions = new ConcurrentHashMap();
-
- public void setCache(CacheSPI cache)
- {
- super.setCache(cache);
- txManager = cache.getTransactionManager();
- txTable = cache.getTransactionTable();
- }
-
public Object invoke(MethodCall m) throws Throwable
{
if (log.isTraceEnabled())
@@ -83,22 +69,8 @@
InvocationContext ctx = cache.getInvocationContext();
- final Transaction suspendedTransaction;
boolean scrubTxsOnExit = false;
- final boolean resumeSuspended;
Option optionOverride = ctx.getOptionOverrides();
- ctx.setTransaction(txManager == null ? null : txManager.getTransaction());
-
- if (optionOverride != null && optionOverride.isFailSilently() && ctx.getTransaction() != null)
- {
- suspendedTransaction = txManager.suspend();
- resumeSuspended = true;
- }
- else
- {
- suspendedTransaction = null;
- resumeSuspended = false;
- }
Object result = null;
@@ -111,13 +83,8 @@
if (MethodDeclarations.isTransactionLifecycleMethod(m.getMethodId()))
{
// this is a prepare, commit, or rollback.
- // start by setting transactional details into InvocationContext.
- ctx.setGlobalTransaction(findGlobalTransaction(m.getArgs()));
-
- if (log.isDebugEnabled()) log.debug("Got gtx from method call " + ctx.getGlobalTransaction());
- ctx.getGlobalTransaction().setRemote(isRemoteGlobalTx(ctx.getGlobalTransaction()));
+ if (log.isDebugEnabled()) log.debug("Got gtx from invocation context " + ctx.getGlobalTransaction());
- //replaceGtx(m, gtxFromMethodCall);
if (ctx.getGlobalTransaction().isRemote()) remoteTransactions.put(ctx.getGlobalTransaction(), NULL);
switch (m.getMethodId())
@@ -165,23 +132,14 @@
}
finally
{
- if (resumeSuspended)
- {
- txManager.resume(suspendedTransaction);
- }
- else
- {
- if (ctx.getTransaction() != null && isValid(ctx.getTransaction()))
- {
- copyInvocationScopeOptionsToTxScope(ctx);
- }
- }
-
// we should scrub txs after every call to prevent race conditions
// basically any other call coming in on the same thread and hijacking any running tx's
// was highlighted in JBCACHE-606
- scrubInvocationCtx(scrubTxsOnExit);
+ if (scrubTxsOnExit)
+ {
+ setTransactionalContext(null, null);
+ }
}
return result;
}
@@ -217,33 +175,9 @@
return retval;
}
- protected GlobalTransaction findGlobalTransaction(Object[] params)
- {
- int clue = 0;
-
- if (params[clue] instanceof GlobalTransaction)
- return (GlobalTransaction) params[clue];
- else
- for (Object param : params) if (param instanceof GlobalTransaction) return (GlobalTransaction) param;
- return null;
- }
-
-
- private void copyInvocationScopeOptionsToTxScope(InvocationContext ctx)
- {
- // notify the transaction entry that this override is in place.
- TransactionEntry entry = txTable.get(ctx.getGlobalTransaction());
- if (entry != null)
- {
- Option txScopeOption = new Option();
- txScopeOption.setCacheModeLocal(ctx.getOptionOverrides() != null && ctx.getOptionOverrides().isCacheModeLocal());
- entry.setOption(txScopeOption);
- }
- }
-
private Object handleRemotePrepare(MethodCall m, GlobalTransaction gtx) throws Throwable
{
- List modifications = (List) m.getArgs()[1];
+ List<MethodCall> modifications = (List<MethodCall>) m.getArgs()[1];
boolean onePhase = (Boolean) m.getArgs()[configuration.isNodeLockingOptimistic() ? 4 : 3];
// Is there a local transaction associated with GTX ?
@@ -413,7 +347,7 @@
* @return
* @throws Throwable
*/
- private Object handleOptimisticPrepare(MethodCall m, GlobalTransaction gtx, List modifications, boolean onePhase, Transaction ltx) throws Throwable
+ private Object handleOptimisticPrepare(MethodCall m, GlobalTransaction gtx, List<MethodCall> modifications, boolean onePhase, Transaction ltx) throws Throwable
{
// TODO: Manik: Refactor this to pass across entire workspace?
Object retval;
@@ -430,7 +364,7 @@
return retval;
}
- private Object handlePessimisticPrepare(MethodCall m, GlobalTransaction gtx, List modifications, boolean commit, Transaction ltx) throws Exception
+ private Object handlePessimisticPrepare(MethodCall m, GlobalTransaction gtx, List<MethodCall> modifications, boolean commit, Transaction ltx) throws Exception
{
boolean success = true;
Object retval;
@@ -512,18 +446,17 @@
return null;
}
- private Object replayModifications(List modifications, Transaction tx)
+ private Object replayModifications(List<MethodCall> modifications, Transaction tx)
{
Object retval = null;
if (modifications != null)
{
- for (Iterator it = modifications.iterator(); it.hasNext();)
+ for (MethodCall modification : modifications)
{
- MethodCall method_call = (MethodCall) it.next();
try
{
- retval = super.invoke(method_call);
+ retval = super.invoke(modification);
if (!isActive(tx))
{
throw new ReplicationException("prepare() failed -- " + "local transaction status is not STATUS_ACTIVE; is " + tx.getStatus());
@@ -553,7 +486,7 @@
*/
private Object handleRemoteCommitRollback(MethodCall m, GlobalTransaction gtx) throws Throwable
{
- Transaction ltx = null;
+ Transaction ltx;
try
{
ltx = getLocalTxForGlobalTx(gtx);
@@ -654,7 +587,8 @@
*/
private Object handleCommitRollback(MethodCall m) throws Throwable
{
- GlobalTransaction gtx = findGlobalTransaction(m.getArgs());
+ //GlobalTransaction gtx = findGlobalTransaction(m.getArgs());
+ GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction();
Object result;
// this must have a local transaction associated if a prepare has been
@@ -824,16 +758,6 @@
// Private helper methods
// --------------------------------------------------------------
- /**
- * Tests if a global transaction originated from a different cache in the cluster
- *
- * @param gtx
- * @return true if the gtx is remote, false if it originated locally.
- */
- private boolean isRemoteGlobalTx(GlobalTransaction gtx)
- {
- return gtx != null && (gtx.getAddress() != null) && (!gtx.getAddress().equals(cache.getLocalAddress()));
- }
/**
* Creates a gtx (if one doesnt exist), a sync handler, and registers the tx.
@@ -944,21 +868,6 @@
return localTx;
}
- private void setInvocationContext(Transaction tx, GlobalTransaction gtx)
- {
- InvocationContext ctx = cache.getInvocationContext();
- ctx.setTransaction(tx);
- ctx.setGlobalTransaction(gtx);
- }
-
- private void scrubInvocationCtx(boolean removeTxs)
- {
- if (removeTxs) setInvocationContext(null, null);
-
- // only scrub options; not tx and gtx
- cache.getInvocationContext().setOptionOverrides(null);
- }
-
// ------------------------------------------------------------------------
// Synchronization classes
// ------------------------------------------------------------------------
@@ -1000,7 +909,7 @@
{
try
{
- setInvocationContext(tx, gtx);
+ setTransactionalContext(tx, gtx);
if (log.isTraceEnabled()) log.trace("calling aftercompletion for " + gtx);
// set any transaction wide options as current for this thread.
if ((entry = txTable.get(gtx)) != null)
@@ -1037,7 +946,7 @@
// clean up the tx table
txTable.remove(gtx);
txTable.remove(tx);
- scrubInvocationCtx(true);
+ setTransactionalContext(null, null);
}
}
@@ -1061,7 +970,7 @@
super.beforeCompletion();
// fetch the modifications before the transaction is committed
// (and thus removed from the txTable)
- setInvocationContext(tx, gtx);
+ setTransactionalContext(tx, gtx);
if (modifications.size() == 0)
{
if (log.isTraceEnabled()) log.trace("No modifications in this tx. Skipping beforeCompletion()");
@@ -1106,7 +1015,7 @@
finally
{
localRollbackOnly = false;
- scrubInvocationCtx(false);
+ setTransactionalContext(null, null);
}
}
1.1 date: 2006/09/06 17:58:20; author: msurtani; state: Exp;JBossCache/src/org/jboss/cache/interceptors/BaseTransactionalContextInterceptor.java
Index: BaseTransactionalContextInterceptor.java
===================================================================
package org.jboss.cache.interceptors;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.GlobalTransaction;
import org.jboss.cache.InvocationContext;
import org.jboss.cache.TransactionEntry;
import org.jboss.cache.TransactionTable;
import org.jboss.cache.config.Option;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
/**
* Class providing some base functionality around manipulating transactions and global transactions withing invocation contexts.
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
*/
public abstract class BaseTransactionalContextInterceptor extends Interceptor
{
protected TransactionTable txTable;
protected TransactionManager txManager;
public void setCache(CacheSPI cache)
{
super.setCache(cache);
txManager = cache.getTransactionManager();
txTable = cache.getTransactionTable();
}
protected void copyInvocationScopeOptionsToTxScope(InvocationContext ctx)
{
// notify the transaction entry that this override is in place.
TransactionEntry entry = txTable.get(ctx.getGlobalTransaction());
if (entry != null)
{
Option txScopeOption = new Option();
txScopeOption.setCacheModeLocal(ctx.getOptionOverrides() != null && ctx.getOptionOverrides().isCacheModeLocal());
entry.setOption(txScopeOption);
}
}
protected void setTransactionalContext(Transaction tx, GlobalTransaction gtx)
{
InvocationContext ctx = cache.getInvocationContext();
log.trace("Setting up transactional context.");
if (log.isTraceEnabled()) log.trace("Setting tx as " + tx + " and gtx as " + gtx);
ctx.setTransaction(tx);
ctx.setGlobalTransaction(gtx);
}
}
More information about the jboss-cvs-commits
mailing list