git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1178398 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Timothy A. Bish 2011-10-03 12:43:51 +00:00
parent 0890672e08
commit e6254c2f8a
1 changed files with 91 additions and 63 deletions

View File

@ -19,8 +19,8 @@ package org.apache.activemq;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.TransactionInProgressException; import javax.jms.TransactionInProgressException;
@ -68,7 +68,8 @@ public class TransactionContext implements XAResource {
private static final Logger LOG = LoggerFactory.getLogger(TransactionContext.class); private static final Logger LOG = LoggerFactory.getLogger(TransactionContext.class);
// XATransactionId -> ArrayList of TransactionContext objects // XATransactionId -> ArrayList of TransactionContext objects
private final static ConcurrentHashMap<TransactionId, List<TransactionContext>> ENDED_XA_TRANSACTION_CONTEXTS = new ConcurrentHashMap<TransactionId, List<TransactionContext>>(); private final static HashMap<TransactionId, List<TransactionContext>> ENDED_XA_TRANSACTION_CONTEXTS =
new HashMap<TransactionId, List<TransactionContext>>();
private final ActiveMQConnection connection; private final ActiveMQConnection connection;
private final LongSequenceGenerator localTransactionIdGenerator; private final LongSequenceGenerator localTransactionIdGenerator;
@ -88,8 +89,21 @@ public class TransactionContext implements XAResource {
} }
public boolean isInXATransaction() { public boolean isInXATransaction() {
return (transactionId != null && transactionId.isXATransaction()) || if (transactionId != null && transactionId.isXATransaction()) {
(!ENDED_XA_TRANSACTION_CONTEXTS.isEmpty() && ENDED_XA_TRANSACTION_CONTEXTS.containsValue(this)); return true;
} else {
if (!ENDED_XA_TRANSACTION_CONTEXTS.isEmpty()) {
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
for(List<TransactionContext> transactions : ENDED_XA_TRANSACTION_CONTEXTS.values()) {
if (transactions.contains(this)) {
return true;
}
}
}
}
}
return false;
} }
public boolean isInLocalTransaction() { public boolean isInLocalTransaction() {
@ -437,6 +451,7 @@ public class TransactionContext implements XAResource {
IntegerResponse response = (IntegerResponse)syncSendPacketWithInterruptionHandling(info); IntegerResponse response = (IntegerResponse)syncSendPacketWithInterruptionHandling(info);
if (XAResource.XA_RDONLY == response.getResult()) { if (XAResource.XA_RDONLY == response.getResult()) {
// transaction stops now, may be syncs that need a callback // transaction stops now, may be syncs that need a callback
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
if (l != null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
@ -447,10 +462,12 @@ public class TransactionContext implements XAResource {
} }
} }
} }
}
return response.getResult(); return response.getResult();
} catch (JMSException e) { } catch (JMSException e) {
LOG.warn("prepare of: " + x + " failed with: " + e, e); LOG.warn("prepare of: " + x + " failed with: " + e, e);
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
if (l != null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
for (TransactionContext ctx : l) { for (TransactionContext ctx : l) {
@ -458,7 +475,9 @@ public class TransactionContext implements XAResource {
ctx.afterRollback(); ctx.afterRollback();
} catch (Throwable ignored) { } catch (Throwable ignored) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("failed to firing afterRollback callbacks on prepare failure, txid: " + x + ", context: " + ctx, ignored); LOG.debug("failed to firing afterRollback callbacks on prepare failure, txid: " +
x + ", context: " + ctx, ignored);
}
} }
} }
} }
@ -495,13 +514,14 @@ public class TransactionContext implements XAResource {
TransactionInfo info = new TransactionInfo(getConnectionId(), x, TransactionInfo.ROLLBACK); TransactionInfo info = new TransactionInfo(getConnectionId(), x, TransactionInfo.ROLLBACK);
syncSendPacketWithInterruptionHandling(info); syncSendPacketWithInterruptionHandling(info);
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
if (l != null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
for (TransactionContext ctx : l) { for (TransactionContext ctx : l) {
ctx.afterRollback(); ctx.afterRollback();
} }
} }
}
} catch (JMSException e) { } catch (JMSException e) {
throw toXAException(e); throw toXAException(e);
} }
@ -534,6 +554,7 @@ public class TransactionContext implements XAResource {
syncSendPacketWithInterruptionHandling(info); syncSendPacketWithInterruptionHandling(info);
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
if (l != null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
for (TransactionContext ctx : l) { for (TransactionContext ctx : l) {
@ -544,10 +565,12 @@ public class TransactionContext implements XAResource {
} }
} }
} }
}
} catch (JMSException e) { } catch (JMSException e) {
LOG.warn("commit of: " + x + " failed with: " + e, e); LOG.warn("commit of: " + x + " failed with: " + e, e);
if (onePhase) { if (onePhase) {
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
if (l != null && !l.isEmpty()) { if (l != null && !l.isEmpty()) {
for (TransactionContext ctx : l) { for (TransactionContext ctx : l) {
@ -561,6 +584,7 @@ public class TransactionContext implements XAResource {
} }
} }
} }
}
throw toXAException(e); throw toXAException(e);
} }
@ -592,8 +616,10 @@ public class TransactionContext implements XAResource {
} catch (JMSException e) { } catch (JMSException e) {
throw toXAException(e); throw toXAException(e);
} }
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
ENDED_XA_TRANSACTION_CONTEXTS.remove(x); ENDED_XA_TRANSACTION_CONTEXTS.remove(x);
} }
}
public boolean isSameRM(XAResource xaResource) throws XAException { public boolean isSameRM(XAResource xaResource) throws XAException {
if (xaResource == null) { if (xaResource == null) {
@ -691,6 +717,7 @@ public class TransactionContext implements XAResource {
// Add our self to the list of contexts that are interested in // Add our self to the list of contexts that are interested in
// post commit/rollback events. // post commit/rollback events.
synchronized(ENDED_XA_TRANSACTION_CONTEXTS) {
List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.get(transactionId); List<TransactionContext> l = ENDED_XA_TRANSACTION_CONTEXTS.get(transactionId);
if (l == null) { if (l == null) {
l = new ArrayList<TransactionContext>(3); l = new ArrayList<TransactionContext>(3);
@ -700,6 +727,7 @@ public class TransactionContext implements XAResource {
l.add(this); l.add(this);
} }
} }
}
// dis-associate // dis-associate
associatedXid = null; associatedXid = null;