From 0be7097d7117695c312e99c413d9030a8101a6a4 Mon Sep 17 00:00:00 2001 From: Stefan CORDES <50696194+ca-stefan-cordes@users.noreply.github.com> Date: Tue, 6 Jul 2021 20:43:15 +0200 Subject: [PATCH 1/3] For suspend use TMSUSPEND and TMRESUME instead of TMSUCCESS TMJOIN Suspend should just TMSUSPEND the transaction and resume just TMRESUME --- .../tm/internal/XAResourceHolderState.java | 4 ++- .../tm/internal/XAResourceManager.java | 27 ++++--------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/btm/src/main/java/bitronix/tm/internal/XAResourceHolderState.java b/btm/src/main/java/bitronix/tm/internal/XAResourceHolderState.java index 716817c4..0be12167 100644 --- a/btm/src/main/java/bitronix/tm/internal/XAResourceHolderState.java +++ b/btm/src/main/java/bitronix/tm/internal/XAResourceHolderState.java @@ -179,7 +179,9 @@ public void end(int flags) throws XAException { } finally { this.suspended = suspended; this.ended = ended; - this.started = false; + if (ended) { + this.started = false; + } } } diff --git a/btm/src/main/java/bitronix/tm/internal/XAResourceManager.java b/btm/src/main/java/bitronix/tm/internal/XAResourceManager.java index 1cc14506..1ae131e3 100644 --- a/btm/src/main/java/bitronix/tm/internal/XAResourceManager.java +++ b/btm/src/main/java/bitronix/tm/internal/XAResourceManager.java @@ -146,7 +146,7 @@ public void suspend() throws XAException { for (XAResourceHolderState xaResourceHolderState : resources) { if (!xaResourceHolderState.isEnded()) { if (log.isDebugEnabled()) log.debug("suspending " + xaResourceHolderState); - xaResourceHolderState.end(XAResource.TMSUCCESS); + xaResourceHolderState.end(XAResource.TMSUSPEND); } } // while } @@ -156,29 +156,12 @@ public void suspend() throws XAException { * @throws XAException if the resource threw an exception during resume. */ public void resume() throws XAException { - // all XAResource needs to be re-enlisted but this must happen - // outside the Scheduler's iteration as enlist() can change the - // collection's content and confuse the iterator. - List toBeReEnlisted = new ArrayList(); - for (XAResourceHolderState xaResourceHolderState : resources) { - if (log.isDebugEnabled()) log.debug("resuming " + xaResourceHolderState); - - // If a prepared statement is (re-)used after suspend/resume is performed its XAResource needs to be - // re-enlisted. This must be done outside this loop or that will confuse the iterator! - toBeReEnlisted.add(new XAResourceHolderState(xaResourceHolderState)); - } - - if (toBeReEnlisted.size() > 0 && log.isDebugEnabled()) log.debug("re-enlisting " + toBeReEnlisted.size() + " resource(s)"); - for (XAResourceHolderState xaResourceHolderState : toBeReEnlisted) { - if (log.isDebugEnabled()) log.debug("re-enlisting resource " + xaResourceHolderState); - try { - enlist(xaResourceHolderState); - xaResourceHolderState.getXAResourceHolder().putXAResourceHolderState(xaResourceHolderState.getXid(), xaResourceHolderState); - } catch (BitronixSystemException ex) { - throw new BitronixXAException("error re-enlisting resource during resume: " + xaResourceHolderState, XAException.XAER_RMERR, ex); + if (!xaResourceHolderState.isEnded()) { + if (log.isDebugEnabled()) log.debug("resuming " + xaResourceHolderState); + xaResourceHolderState.start(XAResource.TMRESUME); } - } + } // while } /** From 16aab812cecf5b15ad409192d71e208db721f1ea Mon Sep 17 00:00:00 2001 From: Stefan CORDES <50696194+ca-stefan-cordes@users.noreply.github.com> Date: Tue, 6 Jul 2021 20:42:39 +0200 Subject: [PATCH 2/3] adapt some tests for suspend use TMSUSPEND and TMRESUME instead of TMSUCCESS TMJOIN Suspend should just TMSUSPEND the transaction and resume just TMRESUME --- .../tm/mock/JdbcSharedConnectionTest.java | 9 ++- .../tm/mock/NewJdbcProperUsageMockTest.java | 13 ++- .../tm/mock/NewJdbcStrangeUsageMockTest.java | 8 +- .../tm/mock/NewJdbcSuspendResumeMockTest.java | 79 ++++++++----------- 4 files changed, 51 insertions(+), 58 deletions(-) diff --git a/btm/src/test/java/bitronix/tm/mock/JdbcSharedConnectionTest.java b/btm/src/test/java/bitronix/tm/mock/JdbcSharedConnectionTest.java index 3401a540..f68c8f2b 100644 --- a/btm/src/test/java/bitronix/tm/mock/JdbcSharedConnectionTest.java +++ b/btm/src/test/java/bitronix/tm/mock/JdbcSharedConnectionTest.java @@ -23,6 +23,7 @@ import java.lang.reflect.Proxy; import java.sql.Connection; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicReference; import javax.transaction.*; @@ -47,17 +48,19 @@ public void testSharedConnectionMultithreaded() throws Exception { tm.begin(); if (log.isDebugEnabled()) log.debug("*** after begin"); - final Transaction suspended = tm.suspend(); + final AtomicReference suspended = new AtomicReference(tm.suspend()); final ArrayList twoConnections = new ArrayList(); Thread thread1 = new Thread() { public void run() { try { - tm.resume(suspended); + tm.resume(suspended.get()); if (log.isDebugEnabled()) log.debug("*** getting connection from DS1"); Connection connection = poolingDataSource1.getConnection(); connection.createStatement(); twoConnections.add(connection); + // remove transaction from the ThreadLocal + suspended.set(tm.suspend()); } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); @@ -70,7 +73,7 @@ public void run() { Thread thread2 = new Thread() { public void run() { try { - tm.resume(suspended); + tm.resume(suspended.get()); if (log.isDebugEnabled()) log.debug("*** getting connection from DS1"); Connection connection = poolingDataSource1.getConnection(); connection.createStatement(); diff --git a/btm/src/test/java/bitronix/tm/mock/NewJdbcProperUsageMockTest.java b/btm/src/test/java/bitronix/tm/mock/NewJdbcProperUsageMockTest.java index eb74c2d2..dd5f44ae 100644 --- a/btm/src/test/java/bitronix/tm/mock/NewJdbcProperUsageMockTest.java +++ b/btm/src/test/java/bitronix/tm/mock/NewJdbcProperUsageMockTest.java @@ -590,19 +590,16 @@ public void testSuspendResume() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(23, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -615,6 +612,8 @@ public void testSuspendResume() throws Exception { assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(21, orderedEvents.size()); } public void testLooseWorkingCaseOutsideOutside() throws Exception { diff --git a/btm/src/test/java/bitronix/tm/mock/NewJdbcStrangeUsageMockTest.java b/btm/src/test/java/bitronix/tm/mock/NewJdbcStrangeUsageMockTest.java index 1760fc8b..abc887a2 100644 --- a/btm/src/test/java/bitronix/tm/mock/NewJdbcStrangeUsageMockTest.java +++ b/btm/src/test/java/bitronix/tm/mock/NewJdbcStrangeUsageMockTest.java @@ -301,12 +301,11 @@ public void testClosingSuspendedConnectionsInDifferentContext() throws Exception List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(18, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -314,8 +313,7 @@ public void testClosingSuspendedConnectionsInDifferentContext() throws Exception assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -324,6 +322,8 @@ public void testClosingSuspendedConnectionsInDifferentContext() throws Exception assertEquals(true, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(17, orderedEvents.size()); } } diff --git a/btm/src/test/java/bitronix/tm/mock/NewJdbcSuspendResumeMockTest.java b/btm/src/test/java/bitronix/tm/mock/NewJdbcSuspendResumeMockTest.java index 1c924828..018bf543 100644 --- a/btm/src/test/java/bitronix/tm/mock/NewJdbcSuspendResumeMockTest.java +++ b/btm/src/test/java/bitronix/tm/mock/NewJdbcSuspendResumeMockTest.java @@ -101,14 +101,12 @@ public void testSimpleWorkingCase() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(13, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -116,6 +114,8 @@ public void testSimpleWorkingCase() throws Exception { assertEquals(true, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(12, orderedEvents.size()); } public void testNoTmJoin() throws Exception { @@ -150,23 +150,21 @@ public void testNoTmJoin() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(15, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); - assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode()); - assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); - assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); - assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); + assertEquals(true, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(12, orderedEvents.size()); } public void testReEnlistmentAfterSuspend() throws Exception { @@ -208,12 +206,11 @@ public void testReEnlistmentAfterSuspend() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(20, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); @@ -223,8 +220,7 @@ public void testReEnlistmentAfterSuspend() throws Exception { assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass()); assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -233,6 +229,8 @@ public void testReEnlistmentAfterSuspend() throws Exception { assertEquals(true, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(19, orderedEvents.size()); } public void testClosingSuspendedConnections() throws Exception { @@ -286,14 +284,12 @@ public void testClosingSuspendedConnections() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(13, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -301,6 +297,8 @@ public void testClosingSuspendedConnections() throws Exception { assertEquals(true, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase()); assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(12, orderedEvents.size()); } public void testInterleavedLocalGlobalTransactions() throws Exception { @@ -336,16 +334,14 @@ public void testInterleavedLocalGlobalTransactions() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(15, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -354,6 +350,8 @@ public void testInterleavedLocalGlobalTransactions() throws Exception { assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i)).getStatus()); assertEquals(1, ((JournalLogEvent) orderedEvents.get(i++)).getJndiNames().size()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(14, orderedEvents.size()); } public void testInterleavedGlobalGlobalTransactionsWithDifferentConnections() throws Exception { @@ -393,12 +391,11 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnections() th List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(23, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); // interleaved transaction assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -412,8 +409,7 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnections() th assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -422,6 +418,8 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnections() th assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i)).getStatus()); assertEquals(1, ((JournalLogEvent) orderedEvents.get(i++)).getJndiNames().size()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(22, orderedEvents.size()); } public void testInterleavedGlobalGlobalTransactionsWithDifferentConnectionsLateSuspend() throws Exception { @@ -464,12 +462,11 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnectionsLateS List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(23, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); // interleaved transaction assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -483,8 +480,7 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnectionsLateS assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); @@ -493,6 +489,8 @@ public void testInterleavedGlobalGlobalTransactionsWithDifferentConnectionsLateS assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i)).getStatus()); assertEquals(1, ((JournalLogEvent) orderedEvents.get(i++)).getJndiNames().size()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(22, orderedEvents.size()); } public void testJoinAfterSuspend() throws Exception { @@ -528,7 +526,6 @@ public void testJoinAfterSuspend() throws Exception { List orderedEvents = EventRecorder.getOrderedEvents(); log.info(EventRecorder.dumpToString()); - assertEquals(25, orderedEvents.size()); int i=0; assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); @@ -537,19 +534,11 @@ public void testJoinAfterSuspend() throws Exception { assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); // suspend happens here - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); - assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMSUSPEND, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag()); // resume happens here - assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm()); - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); - - XAResourceIsSameRmEvent evt = (XAResourceIsSameRmEvent) orderedEvents.get(i++); - XAResource src = (XAResource) evt.getSource(); - XAResource comp = evt.getXAResource(); - assertTrue(poolingDataSource2.findXAResourceHolder(src) != null); - assertTrue(poolingDataSource2.findXAResourceHolder(comp) != null); - - assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); + assertEquals(XAResource.TMRESUME, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag()); assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); @@ -567,6 +556,8 @@ public void testJoinAfterSuspend() throws Exception { assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus()); assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName()); + + assertEquals(23, orderedEvents.size()); } public void testReusePreparedStatementAfterSuspendResume() throws Exception { From 1d75934b55be357c6eb83108d3034e1d076af56e Mon Sep 17 00:00:00 2001 From: Stefan CORDES <50696194+ca-stefan-cordes@users.noreply.github.com> Date: Tue, 6 Jul 2021 21:17:35 +0200 Subject: [PATCH 3/3] accept but still not support TMSUSPEND/TMRESUME on non-XA JDBC connection See bitronix.tm.JtaTest.testRecycleAfterSuspend() (alternative maybe to disable the test as "{@link XAResource#TMSUSPEND} and {@link XAResource#TMRESUME} are not supported.") --- .../tm/resource/jdbc/lrc/LrcXAResource.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/btm/src/main/java/bitronix/tm/resource/jdbc/lrc/LrcXAResource.java b/btm/src/main/java/bitronix/tm/resource/jdbc/lrc/LrcXAResource.java index 7f6902bd..0422c2c0 100644 --- a/btm/src/main/java/bitronix/tm/resource/jdbc/lrc/LrcXAResource.java +++ b/btm/src/main/java/bitronix/tm/resource/jdbc/lrc/LrcXAResource.java @@ -113,6 +113,14 @@ public boolean isSameRM(XAResource xaResource) throws XAException { } public void start(Xid xid, int flag) throws XAException { + if (flag == XAResource.TMRESUME) { + if (state != STARTED) { + throw new BitronixXAException("resource not started on XID " + this.xid, XAException.XAER_PROTO); + } + log.warn("Resume not supported, maybe some commits from the suspend state on XID " + xid); + // Do not throw exception as this is just emulating XA + return; + } if (flag != XAResource.TMNOFLAGS && flag != XAResource.TMJOIN) throw new BitronixXAException("unsupported start flag " + Decoder.decodeXAResourceFlag(flag), XAException.XAER_RMERR); if (xid == null) @@ -161,6 +169,14 @@ else if (state == PREPARED) { } public void end(Xid xid, int flag) throws XAException { + if (flag == XAResource.TMSUSPEND) { + if (state != STARTED) { + throw new BitronixXAException("resource not started on XID " + this.xid, XAException.XAER_PROTO); + } + log.warn("Suspend not supported on XID " + xid + " keep started state."); + // Do not throw exception as this is just emulating XA + return; + } if (flag != XAResource.TMSUCCESS && flag != XAResource.TMFAIL) throw new BitronixXAException("unsupported end flag " + Decoder.decodeXAResourceFlag(flag), XAException.XAER_RMERR); if (xid == null)