From 67606ca651c310d22ffba124eef2fd58e17da596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarre=C3=B1o?= Date: Mon, 24 Jan 2011 19:53:35 +0100 Subject: [PATCH] HHH-5859 - Upgraded to 4.2.0.CR1 Apart from upgrading Infinispan, test transaction manager code has been changed so that read only transactions are not committed twice. --- .../hibernate-infinispan.gradle | 2 +- .../BasicTransactionalTestCase.java | 4 +- .../functional/ConcurrentWriteTest.java | 1 + .../classloader/ClassLoaderTestDAO.java | 13 +-- .../cluster/DualNodeJtaTransactionImpl.java | 83 +++++++++++++++-- .../DualNodeJtaTransactionManagerImpl.java | 9 +- .../infinispan/tm/XaTransactionImpl.java | 91 +++++++++++++++++-- 7 files changed, 173 insertions(+), 30 deletions(-) diff --git a/hibernate-infinispan/hibernate-infinispan.gradle b/hibernate-infinispan/hibernate-infinispan.gradle index 19e6598568..71a0396a53 100644 --- a/hibernate-infinispan/hibernate-infinispan.gradle +++ b/hibernate-infinispan/hibernate-infinispan.gradle @@ -5,7 +5,7 @@ configurations { } dependencies { - infinispanVersion = '4.2.0.CR4' + infinispanVersion = '4.2.1.CR1' jnpVersion = '5.0.3.GA' compile(project(':hibernate-core')) diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java index c18635b230..0ff7ed90df 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java @@ -41,6 +41,8 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase { commitOrRollbackTx(); } + log.info("Entry persisted, let's load and delete it."); + beginTx(); try { Session s = openSession(); @@ -244,7 +246,7 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase { } public void testQueryCache() throws Exception { - Session s = null; + Session s; Item item = new Item("chris", "Chris's Item"); beginTx(); diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java index ade55e5592..4ab1a5c594 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/ConcurrentWriteTest.java @@ -172,6 +172,7 @@ public class ConcurrentWriteTest extends SingleNodeTestCase { assertEquals(customerSlcs.getElementCountInMemory(), 1); assertEquals(customerSlcs.getEntries().size(), 1); + log.info("Add contact to customer {0}", customerId); SecondLevelCacheStatistics contactsCollectionSlcs = getEnvironment().getSessionFactory() .getStatistics().getSecondLevelCacheStatistics(Customer.class.getName() + ".contacts"); assertEquals(1, contactsCollectionSlcs.getPutCount()); diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java index ba76ed9180..587a34246d 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java @@ -156,16 +156,11 @@ public class ClassLoaderTestDAO { public Account getAccount(Integer id) throws Exception { log.debug("Getting account " + id); - tm.begin(); + Session session = sessionFactory.openSession(); try { - Session session = sessionFactory.getCurrentSession(); - Account acct = (Account) session.get(acctClass, id); - tm.commit(); - return acct; - } catch (Exception e) { - log.error("rolling back", e); - tm.rollback(); - throw e; + return (Account) session.get(acctClass, id); + } finally { + session.close(); } } diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java index c9f7d3eaf0..fbe8d93032 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java @@ -44,6 +44,8 @@ import org.infinispan.util.logging.LogFactory; /** * SimpleJtaTransactionImpl variant that works with DualNodeTransactionManagerImpl. + * + * TODO: Merge with single node transaction manager * * @author Brian Stansberry */ @@ -74,12 +76,12 @@ public class DualNodeJtaTransactionImpl implements Transaction { rollback(); } else { status = Status.STATUS_PREPARING; - + for (int i = 0; i < synchronizations.size(); i++) { Synchronization s = (Synchronization) synchronizations.get(i); s.beforeCompletion(); } - + if (!runXaResourcePrepare()) { status = Status.STATUS_ROLLING_BACK; } else { @@ -97,7 +99,6 @@ public class DualNodeJtaTransactionImpl implements Transaction { throw new SystemException(); } } - runXaResourceCommitTx(); @@ -165,7 +166,7 @@ public class DualNodeJtaTransactionImpl implements Transaction { public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException { - enlistedResources.add(xaResource); + enlistedResources.add(new WrappedXaResource(xaResource)); try { xaResource.start(xid, 0); } catch (XAException e) { @@ -179,11 +180,11 @@ public class DualNodeJtaTransactionImpl implements Transaction { SystemException { throw new SystemException("not supported"); } - + public Collection getEnlistedResources() { return enlistedResources; } - + private boolean runXaResourcePrepare() throws SystemException { Collection resources = getEnlistedResources(); for (XAResource res : resources) { @@ -191,7 +192,7 @@ public class DualNodeJtaTransactionImpl implements Transaction { res.prepare(xid); } catch (XAException e) { log.trace("The resource wants to rollback!", e); - throw new SystemException(e.getMessage()); + return false; } catch (Throwable th) { log.error("Unexpected error from resource manager!", th); throw new SystemException(th.getMessage()); @@ -199,7 +200,7 @@ public class DualNodeJtaTransactionImpl implements Transaction { } return true; } - + private void runXaResourceRollback() { Collection resources = getEnlistedResources(); for (XAResource res : resources) { @@ -223,7 +224,7 @@ public class DualNodeJtaTransactionImpl implements Transaction { } return true; } - + private static class DualNodeJtaTransactionXid implements Xid { private static AtomicInteger txIdCounter = new AtomicInteger(0); private int id = txIdCounter.incrementAndGet(); @@ -247,4 +248,68 @@ public class DualNodeJtaTransactionImpl implements Transaction { '}'; } } + + private class WrappedXaResource implements XAResource { + private final XAResource xaResource; + private int prepareResult; + + public WrappedXaResource(XAResource xaResource) { + this.xaResource = xaResource; + } + + @Override + public void commit(Xid xid, boolean b) throws XAException { + // Commit only if not read only. + if (prepareResult != XAResource.XA_RDONLY) + xaResource.commit(xid, b); + else + log.trace("Not committing {0} due to readonly.", xid); + } + + @Override + public void end(Xid xid, int i) throws XAException { + xaResource.end(xid, i); + } + + @Override + public void forget(Xid xid) throws XAException { + xaResource.forget(xid); + } + + @Override + public int getTransactionTimeout() throws XAException { + return xaResource.getTransactionTimeout(); + } + + @Override + public boolean isSameRM(XAResource xaResource) throws XAException { + return xaResource.isSameRM(xaResource); + } + + @Override + public int prepare(Xid xid) throws XAException { + prepareResult = xaResource.prepare(xid); + return prepareResult; + } + + @Override + public Xid[] recover(int i) throws XAException { + return xaResource.recover(i); + } + + @Override + public void rollback(Xid xid) throws XAException { + xaResource.rollback(xid); + } + + @Override + public boolean setTransactionTimeout(int i) throws XAException { + return xaResource.setTransactionTimeout(i); + } + + @Override + public void start(Xid xid, int i) throws XAException { + xaResource.start(xid, i); + } + } } diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java index fd7b30e60b..b305e2a5b0 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java @@ -38,7 +38,9 @@ import org.infinispan.util.logging.LogFactory; /** * Variant of SimpleJtaTransactionManagerImpl that doesn't use a VM-singleton, but rather a set of * impls keyed by a node id. - * + * + * TODO: Merge with single node transaction manager as much as possible + * * @author Brian Stansberry */ public class DualNodeJtaTransactionManagerImpl implements TransactionManager { @@ -106,7 +108,7 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager { public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException, SystemException { - currentTransaction.set((DualNodeJtaTransactionImpl) transaction); + currentTransaction.set(transaction); log.trace(nodeId + ": Resumed " + transaction + " for thread " + Thread.currentThread().getName()); } @@ -145,7 +147,8 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager { } } - public String toString() { + @Override +public String toString() { StringBuffer sb = new StringBuffer(getClass().getName()); sb.append("[nodeId="); sb.append(nodeId); diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java index 0bb50699b3..ce9bccf95c 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java @@ -48,6 +48,7 @@ import org.infinispan.util.logging.LogFactory; */ public class XaTransactionImpl implements Transaction { private static final Log log = LogFactory.getLog(XaTransactionImpl.class); + private int status; private LinkedList synchronizations; private Connection connection; // the only resource we care about is jdbc connection @@ -60,6 +61,12 @@ public class XaTransactionImpl implements Transaction { this.status = Status.STATUS_ACTIVE; } + public XaTransactionImpl(XaTransactionManagerImpl jtaTransactionManager, Xid xid) { + this.jtaTransactionManager = jtaTransactionManager; + this.status = Status.STATUS_ACTIVE; + this.xid = xid; + } + public int getStatus() { return status; } @@ -78,7 +85,11 @@ public class XaTransactionImpl implements Transaction { s.beforeCompletion(); } - runXaResourcePrepare(); + if (!runXaResourcePrepare()) { + status = Status.STATUS_ROLLING_BACK; + } else { + status = Status.STATUS_PREPARED; + } status = Status.STATUS_COMMITTING; @@ -107,6 +118,8 @@ public class XaTransactionImpl implements Transaction { } public void rollback() throws IllegalStateException, SystemException { + status = Status.STATUS_ROLLING_BACK; + runXaResourceRollback(); status = Status.STATUS_ROLLEDBACK; if (connection != null) { @@ -119,11 +132,11 @@ public class XaTransactionImpl implements Transaction { } } - runXaResourceRollback(); - - for (int i = 0; i < synchronizations.size(); i++) { - Synchronization s = (Synchronization) synchronizations.get(i); - s.afterCompletion(status); + if (synchronizations != null) { + for (int i = 0; i < synchronizations.size(); i++) { + Synchronization s = (Synchronization) synchronizations.get(i); + s.afterCompletion(status); + } } // status = Status.STATUS_NO_TRANSACTION; @@ -156,7 +169,7 @@ public class XaTransactionImpl implements Transaction { public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException { - enlistedResources.add(xaResource); + enlistedResources.add(new WrappedXaResource(xaResource)); try { xaResource.start(xid, 0); } catch (XAException e) { @@ -237,4 +250,68 @@ public class XaTransactionImpl implements Transaction { '}'; } } + + private class WrappedXaResource implements XAResource { + private final XAResource xaResource; + private int prepareResult; + + public WrappedXaResource(XAResource xaResource) { + this.xaResource = xaResource; + } + + @Override + public void commit(Xid xid, boolean b) throws XAException { + // Commit only if not read only. + if (prepareResult != XAResource.XA_RDONLY) + xaResource.commit(xid, b); + else + log.trace("Not committing {0} due to readonly.", xid); + } + + @Override + public void end(Xid xid, int i) throws XAException { + xaResource.end(xid, i); + } + + @Override + public void forget(Xid xid) throws XAException { + xaResource.forget(xid); + } + + @Override + public int getTransactionTimeout() throws XAException { + return xaResource.getTransactionTimeout(); + } + + @Override + public boolean isSameRM(XAResource xaResource) throws XAException { + return xaResource.isSameRM(xaResource); + } + + @Override + public int prepare(Xid xid) throws XAException { + prepareResult = xaResource.prepare(xid); + return prepareResult; + } + + @Override + public Xid[] recover(int i) throws XAException { + return xaResource.recover(i); + } + + @Override + public void rollback(Xid xid) throws XAException { + xaResource.rollback(xid); + } + + @Override + public boolean setTransactionTimeout(int i) throws XAException { + return xaResource.setTransactionTimeout(i); + } + + @Override + public void start(Xid xid, int i) throws XAException { + xaResource.start(xid, i); + } + } }