Skip to content
Permalink
Browse files
GERONIMO-5519 match up the xid with the name during recovery. Add som…
…e more tracing. Merge from 2.1 branch rev 984273

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/txmanager/trunk@984471 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
djencks committed Aug 11, 2010
1 parent b55c8a7 commit e048e7875a1d08a40eb5291525392ff81304f6bd
Showing 6 changed files with 97 additions and 73 deletions.
@@ -43,7 +43,7 @@ public RecoverTask(RetryScheduler retryScheduler, NamedXAResourceFactory namedXA
this.recoverableTransactionManager = recoverableTransactionManager;
}

@Override
// @Override
public void run() {
try {
NamedXAResource namedXAResource = namedXAResourceFactory.getNamedXAResource();
@@ -74,9 +74,11 @@ public synchronized void recoverLog() throws XAException {
}
for (XidBranchesPair xidBranchesPair : preparedXids) {
Xid xid = xidBranchesPair.getXid();
log.trace("read prepared global xid from log: " + toString(xid));
if (xidFactory.matchesGlobalId(xid.getGlobalTransactionId())) {
ourXids.put(new ByteArrayWrapper(xid.getGlobalTransactionId()), xidBranchesPair);
for (TransactionBranchInfo transactionBranchInfo : xidBranchesPair.getBranches()) {
log.trace("read branch from log: " + transactionBranchInfo.toString());
String name = transactionBranchInfo.getResourceName();
Set<XidBranchesPair> transactionsForName = nameToOurTxMap.get(name);
if (transactionsForName == null) {
@@ -86,6 +88,7 @@ public synchronized void recoverLog() throws XAException {
transactionsForName.add(xidBranchesPair);
}
} else {
log.trace("read external prepared xid from log: " + toString(xid));
TransactionImpl externalTx = new ExternalTransaction(xid, txLog, retryScheduler, xidBranchesPair.getBranches());
externalXids.put(xid, externalTx);
externalGlobalIdMap.put(xid.getGlobalTransactionId(), externalTx);
@@ -99,6 +102,7 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
Xid[] prepared = xaResource.recover(XAResource.TMSTARTRSCAN + XAResource.TMENDRSCAN);
for (int i = 0; prepared != null && i < prepared.length; i++) {
Xid xid = prepared[i];
log.trace("considering recovered xid from\n name: " + xaResource.getName() + "\n " + toString(xid));
ByteArrayWrapper globalIdWrapper = new ByteArrayWrapper(xid.getGlobalTransactionId());
XidBranchesPair xidNamesPair = ourXids.get(globalIdWrapper);

@@ -107,17 +111,21 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
// Only commit if this NamedXAResource was the XAResource for the transaction.
// Otherwise, wait for recoverResourceManager to be called for the actual XAResource
// This is a bit wasteful, but given our management of XAResources by "name", is about the best we can do.
if (isNameInTransaction(xidNamesPair, name)) {
if (isNameInTransaction(xidNamesPair, name, xid)) {
log.trace("This xid was prepared from this XAResource: committing");
try {
xaResource.commit(xid, false);
} catch(XAException e) {
recoveryErrors.add(e);
log.error("Recovery error", e);
}
removeNameFromTransaction(xidNamesPair, name, true);
} else {
log.trace("This xid was prepared from another XAResource, ignoring");
}
} else if (xidFactory.matchesGlobalId(xid.getGlobalTransactionId())) {
//ours, but prepare not logged
log.trace("this xid was initiated from this tm but not prepared: rolling back");
try {
xaResource.rollback(xid);
} catch (XAException e) {
@@ -129,13 +137,15 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
TransactionImpl externalTx = externalGlobalIdMap.get(xid.getGlobalTransactionId());
if (externalTx == null) {
//we did not prepare this branch, rollback.
log.trace("this xid is from an external transaction and was not prepared: rolling back");
try {
xaResource.rollback(xid);
} catch (XAException e) {
recoveryErrors.add(e);
log.error("Could not roll back", e);
}
} else {
log.trace("this xid is from an external transaction and was prepared in this tm. Waiting for instructions from transaction originator");
//we prepared this branch, must wait for commit/rollback command.
externalTx.addBranchXid(xaResource, xid);
}
@@ -150,15 +160,21 @@ public synchronized void recoverResourceManager(NamedXAResource xaResource) thro
}
}

private boolean isNameInTransaction(XidBranchesPair xidBranchesPair, String name) {
private boolean isNameInTransaction(XidBranchesPair xidBranchesPair, String name, Xid xid) {
for (TransactionBranchInfo transactionBranchInfo : xidBranchesPair.getBranches()) {
if (name.equals(transactionBranchInfo.getResourceName())) {
if (name.equals(transactionBranchInfo.getResourceName()) && equals(xid, transactionBranchInfo.getBranchXid())) {
return true;
}
}
return false;
}


private boolean equals(Xid xid1, Xid xid2) {
return xid1.getFormatId() == xid1.getFormatId()
&& Arrays.equals(xid1.getBranchQualifier(), xid2.getBranchQualifier())
&& Arrays.equals(xid1.getGlobalTransactionId(), xid2.getGlobalTransactionId());
}

private void removeNameFromTransaction(XidBranchesPair xidBranchesPair, String name, boolean warn) {
int removed = 0;
for (Iterator branches = xidBranchesPair.getBranches().iterator(); branches.hasNext();) {
@@ -206,6 +222,28 @@ public synchronized Map<Xid, TransactionImpl> getExternalXids() {
return new HashMap<Xid, TransactionImpl>(externalXids);
}

private static String toString(Xid xid) {
if (xid instanceof XidImpl) {
return xid.toString();
}
StringBuilder s = new StringBuilder();
s.append("[Xid:class=").append(xid.getClass().getSimpleName()).append(":globalId=");
byte[] globalId = xid.getGlobalTransactionId();
for (int i = 0; i < globalId.length; i++) {
s.append(Integer.toHexString(globalId[i]));
}
s.append(",length=").append(globalId.length);
s.append(",branchId=");
byte[] branchId = xid.getBranchQualifier();
for (int i = 0; i < branchId.length; i++) {
s.append(Integer.toHexString(branchId[i]));
}
s.append(",length=");
s.append(branchId.length);
s.append("]");
return s.toString();
}

private static class ByteArrayWrapper {
private final byte[] bytes;
private final int hashCode;
@@ -32,6 +32,8 @@ public class TransactionBranchInfoImpl implements TransactionBranchInfo {
private final String resourceName;

public TransactionBranchInfoImpl(Xid branchXid, String resourceName) {
if (resourceName == null) throw new NullPointerException("resourceName");
if (branchXid == null) throw new NullPointerException("branchXid");
this.branchXid = branchXid;
this.resourceName = resourceName;
}
@@ -43,4 +45,16 @@ public Xid getBranchXid() {
public String getResourceName() {
return resourceName;
}

@Override
public String toString() {
StringBuilder b = new StringBuilder("[Transaction branch:\n");
b.append(" name:").append(resourceName);
b.append("\n branchId: ");
for (byte i : branchXid.getBranchQualifier()) {
b.append(Integer.toHexString(i));
}
b.append("\n]\n");
return b.toString();
}
}
@@ -49,8 +49,8 @@ public void testDummy() throws Exception {}

public void test2ResOnlineAfterRecoveryStart() throws Exception {
Xid[] xids = getXidArray(XID_COUNT);
MockXAResource xares1 = new MockXAResource(RM1, xids);
MockXAResource xares2 = new MockXAResource(RM2, xids);
MockXAResource xares1 = new MockXAResource(RM1);
MockXAResource xares2 = new MockXAResource(RM2);
MockTransactionInfo[] txInfos = makeTxInfos(xids);
addBranch(txInfos, xares1);
addBranch(txInfos, xares2);
@@ -89,9 +89,9 @@ public void test3ResOnlineAfterRecoveryStart() throws Exception {
tmp.addAll(xids23List);
Xid[] xids3 = (Xid[]) tmp.toArray(new Xid[6]);

MockXAResource xares1 = new MockXAResource(RM1, xids1);
MockXAResource xares2 = new MockXAResource(RM2, xids2);
MockXAResource xares3 = new MockXAResource(RM3, xids3);
MockXAResource xares1 = new MockXAResource(RM1);
MockXAResource xares2 = new MockXAResource(RM2);
MockXAResource xares3 = new MockXAResource(RM3);
MockTransactionInfo[] txInfos12 = makeTxInfos(xids12);
addBranch(txInfos12, xares1);
addBranch(txInfos12, xares2);
@@ -140,12 +140,13 @@ private Xid[] getXidArray(int i) {
return xids;
}

private void addBranch(MockTransactionInfo[] txInfos, MockXAResource xaRes) {
private void addBranch(MockTransactionInfo[] txInfos, MockXAResource xaRes) throws XAException {
for (int i = 0; i < txInfos.length; i++) {
MockTransactionInfo txInfo = txInfos[i];
Xid globalXid = txInfo.globalXid;
Xid branchXid = xidFactory.createBranch(globalXid, branchCounter++);
txInfo.branches.add(new MockTransactionBranchInfo(xaRes.getName(), branchXid));
xaRes.start(branchXid, 0);
txInfo.branches.add(new TransactionBranchInfoImpl(branchXid, xaRes.getName()));
}
}

@@ -161,13 +162,12 @@ private MockTransactionInfo[] makeTxInfos(Xid[] xids) {
private static class MockXAResource implements NamedXAResource {

private final String name;
private final Xid[] xids;
private final List committed = new ArrayList();
private final List rolledBack = new ArrayList();
private final List<Xid> xids = new ArrayList<Xid>();
private final List<Xid> committed = new ArrayList<Xid>();
private final List<Xid> rolledBack = new ArrayList<Xid>();

public MockXAResource(String name, Xid[] xids) {
public MockXAResource(String name) {
this.name = name;
this.xids = xids;
}

public String getName() {
@@ -197,7 +197,7 @@ public int prepare(Xid xid) throws XAException {
}

public Xid[] recover(int flag) throws XAException {
return xids;
return xids.toArray(new Xid[xids.size()]);
}

public void rollback(Xid xid) throws XAException {
@@ -209,6 +209,7 @@ public boolean setTransactionTimeout(int seconds) throws XAException {
}

public void start(Xid xid, int flags) throws XAException {
xids.add(xid);
}

public List getCommitted() {
@@ -232,21 +233,4 @@ public MockTransactionInfo(Xid globalXid, List branches) {
}
}

private static class MockTransactionBranchInfo implements TransactionBranchInfo {
private final String name;
private final Xid branchXid;

public MockTransactionBranchInfo(String name, Xid branchXid) {
this.name = name;
this.branchXid = branchXid;
}

public String getResourceName() {
return name;
}

public Xid getBranchXid() {
return branchXid;
}
}
}
@@ -33,9 +33,9 @@
* */
public class MockLog implements TransactionLog {

final Map prepared = new HashMap();
final List committed = new ArrayList();
final List rolledBack = new ArrayList();
final Map<Xid, Recovery.XidBranchesPair> prepared = new HashMap<Xid, Recovery.XidBranchesPair>();
final List<Xid> committed = new ArrayList<Xid>();
final List<Xid> rolledBack = new ArrayList<Xid>();

public void begin(Xid xid) throws LogException {
}
@@ -56,8 +56,8 @@ public void rollback(Xid xid, Object logMark) throws LogException {
rolledBack.add(xid);
}

public Collection recover(XidFactory xidFactory) throws LogException {
Map copy = new HashMap(prepared);
public Collection<Recovery.XidBranchesPair> recover(XidFactory xidFactory) throws LogException {
Map<Xid, Recovery.XidBranchesPair> copy = new HashMap<Xid, Recovery.XidBranchesPair>(prepared);
copy.keySet().removeAll(committed);
copy.keySet().removeAll(rolledBack);
return copy.values();

0 comments on commit e048e78

Please sign in to comment.