[JBoss JIRA] Created: (ISPN-887) XAResource implementation improvements (TransactionalXAResource)
by Mircea Markus (JIRA)
XAResource implementation improvements (TransactionalXAResource)
----------------------------------------------------------------
Key: ISPN-887
URL: https://issues.jboss.org/browse/ISPN-887
Project: Infinispan
Issue Type: Feature Request
Components: Transactions
Affects Versions: 4.2.0.Final
Reporter: Mircea Markus
Assignee: Manik Surtani
Fix For: 5.0.0.Final
Reviewing the code with Jonathan Halliday has brought the following aspects (see TODOs below):
package org.infinispan.transaction.xa;
import org.infinispan.commands.CommandsFactory;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.commands.tx.RollbackCommand;
import org.infinispan.config.Configuration;
import org.infinispan.context.InvocationContextContainer;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.interceptors.InterceptorChain;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
/**
* This acts both as an local {@link org.infinispan.transaction.xa.CacheTransaction} and implementor of an {@link
* javax.transaction.xa.XAResource} that will be called by tx manager on various tx stages.
*
* @author Mircea.Markus(a)jboss.com
* @since 4.0
*/
public class TransactionXaAdapter implements XAResource {
private static final Log log = LogFactory.getLog(TransactionXaAdapter.class);
private static boolean trace = log.isTraceEnabled();
//todo - comment why timeout is not used
// - it is useful only if TM and client are in separate processes and TM might fail. this is because a client might tm.begin and then the TM (running separate process) crashes
// - in this scenario the TM won't ever call XAResource.rollback, so these resources would be held there forever
// - not affecting us as in all scenarios TM&XAResource are collocated
private int txTimeout;
private final InvocationContextContainer icc;
private final InterceptorChain invoker;
private final CommandsFactory commandsFactory;
private final Configuration configuration;
private final TransactionTable txTable;
/**
* XAResource is associated with a transaction between enlistment (XAResource.start()) XAResource.end(). It's only the
* boundary methods (prepare, commit, rollback) that need to be "stateless".
* Reefer to section 3.4.4 from JTA spec v.1.1
*/
private final LocalTransaction localTransaction;
public TransactionXaAdapter(LocalTransaction localTransaction, TransactionTable txTable, CommandsFactory commandsFactory,
Configuration configuration, InterceptorChain invoker, InvocationContextContainer icc) {
this.localTransaction = localTransaction;
this.txTable = txTable;
this.commandsFactory = commandsFactory;
this.configuration = configuration;
this.invoker = invoker;
this.icc = icc;
}
/**
* This can be call for any transaction object. See Section 3.4.6 (Resource Sharing) from JTA spec v1.1.
*/
public int prepare(Xid xid) throws XAException {
//todo if I throw an exception here then I should also cleanup resources as .rollback might never be called!!
LocalTransaction localTransaction = getLocalTransactionAndValidate(xid);
//todo - same as last comment
validateNotMarkedForRollback(localTransaction);
if (configuration.isOnePhaseCommit()) {
if (trace) log.trace("Received prepare for tx: {0}. Skipping call as 1PC will be used.", xid);
return XA_OK;
}
PrepareCommand prepareCommand = commandsFactory.buildPrepareCommand(localTransaction.getGlobalTransaction(), localTransaction.getModifications(), configuration.isOnePhaseCommit());
if (trace) log.trace("Sending prepare command through the chain: " + prepareCommand);
LocalTxInvocationContext ctx = icc.createTxInvocationContext();
ctx.setLocalTransaction(localTransaction);
try {
invoker.invoke(ctx, prepareCommand);
if (localTransaction.isReadOnly()) {
if (trace) log.trace("Readonly transaction: " + localTransaction.getGlobalTransaction());
// force a cleanup to release any objects held. Some TMs don't call commit if it is a READ ONLY tx. See ISPN-845
commit(xid, false);
return XA_RDONLY;
} else {
return XA_OK;
}
} catch (Throwable e) {
// todo if I throw this exception make sure that all locks are 100% cleaned up, as TM won't do any rollback call on it.
// todo - handle this! -> if only a node fails to ack tx prepare, and that node is still part of the cluster, it needs to be sync with tx state.
// one way of doing this is by pushing the tx state to that node until one of two happens: a) node ack or b) node is shunned from the cluster
log.error("Error while processing PrepareCommand", e);
throw new XAException(XAException.XAER_RMERR);
}
}
/**
* Same comment as for {@link #prepare(javax.transaction.xa.Xid)} applies for commit.
*/
public void commit(Xid xid, boolean isOnePhase) throws XAException {
LocalTransaction localTransaction = getLocalTransactionAndValidate(xid);
if (trace) log.trace("committing transaction {0}", localTransaction.getGlobalTransaction());
try {
LocalTxInvocationContext ctx = icc.createTxInvocationContext();
ctx.setLocalTransaction(localTransaction);
// todo this needs to be split in two:
// - configuration.isOnePhaseCommit() this is not "as important", as the user ack that it doesn't "really" need consistency
// - on the other case ("isOnePhase"==true) make sure that this method either commits successfully or it fails and cleans up logs eventually
if (configuration.isOnePhaseCommit() || isOnePhase) {
validateNotMarkedForRollback(localTransaction);
if (trace) log.trace("Doing an 1PC prepare call on the interceptor chain");
PrepareCommand command = commandsFactory.buildPrepareCommand(localTransaction.getGlobalTransaction(), localTransaction.getModifications(), true);
try {
invoker.invoke(ctx, command);
} catch (Throwable e) {
log.error("Error while processing 1PC PrepareCommand", e);
throw new XAException(XAException.XAER_RMERR);
}
} else {
CommitCommand commitCommand = commandsFactory.buildCommitCommand(localTransaction.getGlobalTransaction());
try {
invoker.invoke(ctx, commitCommand);
} catch (Throwable e) {
log.error("Error while processing 1PC PrepareCommand", e);
throw new XAException(XAException.XAER_RMERR);
}
}
} finally {
cleanup(localTransaction);
}
}
/**
* Same comment as for {@link #prepare(javax.transaction.xa.Xid)} applies for commit.
*/
public void rollback(Xid xid) throws XAException {
rollbackImpl(xid, commandsFactory, icc, invoker, txTable);
}
public static void rollbackImpl(Xid xid, CommandsFactory commandsFactory, InvocationContextContainer icc, InterceptorChain invoker, TransactionTable txTable) throws XAException {
LocalTransaction localTransaction = txTable.getLocalTransaction(xid);
if (localTransaction == null) {
if (trace) log.trace("no tx found for {0}", xid);
throw new XAException(XAException.XAER_NOTA);
}
if (trace) log.trace("rollback transaction {0} ", localTransaction.getGlobalTransaction());
RollbackCommand rollbackCommand = commandsFactory.buildRollbackCommand(localTransaction.getGlobalTransaction());
LocalTxInvocationContext ctx = icc.createTxInvocationContext();
ctx.setLocalTransaction(localTransaction);
try {
invoker.invoke(ctx, rollbackCommand);
} catch (Throwable e) {
log.error("Exception while rollback", e);
throw new XAException(XAException.XA_HEURHAZ);
} finally {
cleanupImpl(localTransaction, txTable, icc);
}
}
private LocalTransaction getLocalTransactionAndValidate(Xid xid) throws XAException {
LocalTransaction localTransaction1 = txTable.getLocalTransaction(xid);
if (localTransaction1 == null) {
log.error("This should not happen when XAResource and TM are in the same process! No tx found for {0}", xid);
throw new XAException(XAException.XAER_NOTA);
}
return localTransaction1;
}
public void start(Xid xid, int i) throws XAException {
localTransaction.setXid(xid);
txTable.addLocalTransactionMapping(localTransaction);
if (trace) log.trace("start called on tx " + this.localTransaction.getGlobalTransaction());
}
public void end(Xid xid, int i) throws XAException {
if (trace) log.trace("end called on tx " + this.localTransaction.getGlobalTransaction());
}
public void forget(Xid xid) throws XAException {
if (trace) log.trace("forget called");
}
public int getTransactionTimeout() throws XAException {
if (trace) log.trace("start called");
return txTimeout;
}
public boolean isSameRM(XAResource xaResource) throws XAException {
if (!(xaResource instanceof TransactionXaAdapter)) {
return false;
}
TransactionXaAdapter other = (TransactionXaAdapter) xaResource;
return other.equals(this);
}
public Xid[] recover(int i) throws XAException {
if (trace) log.trace("recover called: " + i);
return null;
}
public boolean setTransactionTimeout(int i) throws XAException {
this.txTimeout = i;
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TransactionXaAdapter)) return false;
TransactionXaAdapter that = (TransactionXaAdapter) o;
return this.localTransaction.equals(that.localTransaction);
}
@Override
public int hashCode() {
return localTransaction.getGlobalTransaction().hashCode();
}
@Override
public String toString() {
return "TransactionXaAdapter{" +
"localTransaction=" + localTransaction +
'}';
}
private void validateNotMarkedForRollback(LocalTransaction localTransaction) throws XAException {
if (localTransaction.isMarkedForRollback()) {
if (trace) log.trace("Transaction already marked for rollback: {0}", localTransaction);
throw new XAException(XAException.XA_RBROLLBACK);
}
}
private void cleanup(LocalTransaction localTransaction) {
TransactionXaAdapter.cleanupImpl(localTransaction, txTable, icc);
}
private static void cleanupImpl(LocalTransaction localTransaction, TransactionTable txTable, InvocationContextContainer icc) {
txTable.removeLocalTransaction(localTransaction);
icc.suspend();
}
}
--
This message is automatically generated by JIRA.
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
13 years, 7 months
[JBoss JIRA] Created: (ISPN-1063) Validation in TransactionFactory.init should be moved to ConfigurationValidatingVisitor
by Galder Zamarreño (JIRA)
Validation in TransactionFactory.init should be moved to ConfigurationValidatingVisitor
---------------------------------------------------------------------------------------
Key: ISPN-1063
URL: https://issues.jboss.org/browse/ISPN-1063
Project: Infinispan
Issue Type: Enhancement
Components: Configuration, Transactions
Reporter: Galder Zamarreño
Assignee: Mircea Markus
Fix For: 5.0.0.CR1
2:25:00 PM galderz: mmarkus: hi
2:25:26 PM mmarkus: hi galderz
2:26:11 PM galderz: hey mmarkus, i was wondering if the validation in TransactionFactory.init would be better suited for ConfigurationValidatingVisitor ?
2:26:30 PM galderz: i mean, the validation about the incompatible configuration options
2:28:49 PM mmarkus: galderz: which validation exactly? there's no validation in TransactionFactory.init ..
2:33:51 PM galderz: if (txFactoryEnum == null) { ....
2:34:01 PM galderz: Unsupported combination (dldEnabled, recoveryEnabled, xa) = (%s, %s, %s)
2:34:14 PM galderz: that's validation of the configuration afact
2:34:28 PM galderz: boolean dldEnabled = configuration.isEnableDeadlockDetection();
boolean recoveryEnabled = configuration.isTransactionRecoveryEnabled();
boolean xa = !configuration.isUseSynchronizationForTransactions();
2:37:58 PM mmarkus: galderz: yes, good point it should move to ConfigurationValidatingVisitor
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
13 years, 7 months
[JBoss JIRA] Created: (ISPN-1008) Conditional replace/remove not returning previous value in Java Hot Rod client
by Galder Zamarreño (JIRA)
Conditional replace/remove not returning previous value in Java Hot Rod client
------------------------------------------------------------------------------
Key: ISPN-1008
URL: https://issues.jboss.org/browse/ISPN-1008
Project: Infinispan
Issue Type: Bug
Components: Cache Server
Affects Versions: 5.0.0.ALPHA3, 4.2.1.FINAL
Reporter: Galder Zamarreño
Assignee: Mircea Markus
Fix For: 5.0.0.CR1
The following RemoteCache APIs (and their variants) are not correctly defined:
boolean replaceWithVersion(K key, V newValue, long version);
boolean removeWithVersion(K key, long version);
The protocol allows for the previous value to be returned if Flag.FORCE_RETURN_VALUE is used, and these APIs do not accomodate that.
We should think whether it makes sense to keep the protocol as is. Does returning previous value help at all with conditional operations like these?
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
13 years, 7 months
[JBoss JIRA] Created: (ISPN-530) Hot Rod client should load balance between different owners for a key
by Galder Zamarreno (JIRA)
Hot Rod client should load balance between different owners for a key
---------------------------------------------------------------------
Key: ISPN-530
URL: https://jira.jboss.org/browse/ISPN-530
Project: Infinispan
Issue Type: Feature Request
Components: Cache Server
Reporter: Galder Zamarreno
Assignee: Mircea Markus
Fix For: 5.0.0.BETA1
While doing the demo for JUDCon, I realised that smart routing on the client side always choses the same node for the same key.
IOW, assume you have k1 stored in nodes A, B and the cluster is formed of nodes A, B and C. Now, when the client figures out that the owner is A, any further requests on k1 will be sent to A. This has the possibility of overloading A.
I think the client should, from the given list of owners of a key, do round robin between them for requests on the same key.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
13 years, 7 months
[JBoss JIRA] Created: (ISPN-997) getting java.io.IOException: Unsupported protocol version 48
by Kavita Patil (JIRA)
getting java.io.IOException: Unsupported protocol version 48
------------------------------------------------------------
Key: ISPN-997
URL: https://issues.jboss.org/browse/ISPN-997
Project: Infinispan
Issue Type: Bug
Components: Cache Server, Marshalling
Affects Versions: 4.2.0.Final
Environment: Red Hat 3.4.6-2
Reporter: Kavita Patil
Assignee: Manik Surtani
Hi,
I Have a 2 infinispan node cluster setup. I am facing problem when i try to access the cache entries inserted in Node1 from Node2. I am using JDBC shared cacheloader. Exception looks like below..
Reading the keys inserted in Node1
Mar 16, 2011 1:57:44 AM org.infinispan.loaders.jdbc.JdbcUtil unmarshall
SEVERE: I/O error while unmarshalling from stream
java.io.IOException: Unsupported protocol version 48
at org.jboss.marshalling.river.RiverUnmarshaller.doStart(RiverUnmarshaller.java:1167)
at org.jboss.marshalling.AbstractUnmarshaller.start(AbstractUnmarshaller.java:389)
at org.infinispan.marshall.jboss.GenericJBossMarshaller.startObjectInput(GenericJBossMarshaller.java:169)
at org.infinispan.marshall.VersionAwareMarshaller.startObjectInput(VersionAwareMarshaller.java:155)
at org.infinispan.marshall.VersionAwareMarshaller.objectFromByteBuffer(VersionAwareMarshaller.java:112)
at org.infinispan.marshall.AbstractStreamingMarshaller.objectFromInputStream(AbstractStreamingMarshaller.java:23)
at org.infinispan.loaders.jdbc.JdbcUtil.unmarshall(JdbcUtil.java:88)
at org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore.readStoredEntry(JdbcStringBasedCacheStore.java:371)
at org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore.loadLockSafe(JdbcStringBasedCacheStore.java:296)
at org.infinispan.loaders.LockSupportCacheStore.load(LockSupportCacheStore.java:100)
at org.infinispan.interceptors.CacheLoaderInterceptor.loadIfNeeded(CacheLoaderInterceptor.java:149)
at org.infinispan.interceptors.CacheLoaderInterceptor.loadIfNeededAndUpdateStats(CacheLoaderInterceptor.java:218)
at org.infinispan.interceptors.CacheLoaderInterceptor.visitGetKeyValueCommand(CacheLoaderInterceptor.java:89)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:132)
at org.infinispan.commands.AbstractVisitor.visitGetKeyValueCommand(AbstractVisitor.java:88)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.TxInterceptor.enlistReadAndInvokeNext(TxInterceptor.java:169)
at org.infinispan.interceptors.TxInterceptor.visitGetKeyValueCommand(TxInterceptor.java:160)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:87)
at org.infinispan.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:58)
at org.infinispan.commands.AbstractVisitor.visitGetKeyValueCommand(AbstractVisitor.java:88)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:273)
at org.infinispan.CacheDelegate.get(CacheDelegate.java:207)
at com.hp.uup.cache.examples.EmbeddedCacheClusterNode2.main(EmbeddedCacheClusterNode2.java:58)
Mar 16, 2011 1:57:44 AM org.infinispan.interceptors.InvocationContextInterceptor handleAll
SEVERE: Execution error:
org.infinispan.loaders.CacheLoaderException: I/O error while unmarshalling from stream
at org.infinispan.loaders.jdbc.JdbcUtil.unmarshall(JdbcUtil.java:92)
at org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore.readStoredEntry(JdbcStringBasedCacheStore.java:371)
at org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore.loadLockSafe(JdbcStringBasedCacheStore.java:296)
at org.infinispan.loaders.LockSupportCacheStore.load(LockSupportCacheStore.java:100)
at org.infinispan.interceptors.CacheLoaderInterceptor.loadIfNeeded(CacheLoaderInterceptor.java:149)
at org.infinispan.interceptors.CacheLoaderInterceptor.loadIfNeededAndUpdateStats(CacheLoaderInterceptor.java:218)
at org.infinispan.interceptors.CacheLoaderInterceptor.visitGetKeyValueCommand(CacheLoaderInterceptor.java:89)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:132)
at org.infinispan.commands.AbstractVisitor.visitGetKeyValueCommand(AbstractVisitor.java:88)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.TxInterceptor.enlistReadAndInvokeNext(TxInterceptor.java:169)
at org.infinispan.interceptors.TxInterceptor.visitGetKeyValueCommand(TxInterceptor.java:160)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:118)
at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:87)
at org.infinispan.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:58)
at org.infinispan.commands.AbstractVisitor.visitGetKeyValueCommand(AbstractVisitor.java:88)
at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:59)
at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:273)
at org.infinispan.CacheDelegate.get(CacheDelegate.java:207)
at com.hp.uup.cache.examples.EmbeddedCacheClusterNode2.main(EmbeddedCacheClusterNode2.java:58)
Caused by: java.io.IOException: Unsupported protocol version 48
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
13 years, 8 months