@Override public void run() { txMgr.removeHostedTXState(txid); // replace with new TXState txMgr.getOrSetHostedTXState(txid, msg); } });
@Test public void clientTransactionsToBeExpiredIsScheduledToBeRemoved() { doReturn(1).when(spyTxMgr).getTransactionTimeToLive(); TXId txId1 = mock(TXId.class); TXId txId2 = mock(TXId.class); TXId txId3 = mock(TXId.class); tx1 = spyTxMgr.getOrSetHostedTXState(txId1, msg); tx2 = spyTxMgr.getOrSetHostedTXState(txId2, msg); Set<TXId> set = new HashSet<>(); set.add(txId1); set.add(txId2); spyTxMgr.expireDisconnectedClientTransactions(set, false); verify(spyTxMgr, times(1)).scheduleToRemoveClientTransaction(eq(txId1), eq(1100L)); verify(spyTxMgr, times(1)).scheduleToRemoveClientTransaction(eq(txId2), eq(1100L)); verify(spyTxMgr, never()).scheduleToRemoveClientTransaction(eq(txId3), eq(1100L)); }
/** * Associate the remote txState with the thread processing this message. Also, we acquire a lock * on the txState, on which this thread operates. Some messages like SizeMessage should not create * a new txState. * * @return {@link TXStateProxy} the txProxy for the transactional message */ public TXStateProxy masqueradeAs(TransactionMessage msg) throws InterruptedException { if (msg.getTXUniqId() == NOTX || !msg.canParticipateInTransaction()) { return null; } TXId key = new TXId(msg.getMemberToMasqueradeAs(), msg.getTXUniqId()); TXStateProxy val = getOrSetHostedTXState(key, msg); if (val != null) { boolean success = getLock(val, key); while (!success) { val = getOrSetHostedTXState(key, msg); if (val != null) { success = getLock(val, key); } else { break; } } } if (logger.isDebugEnabled()) { logger.debug("masqueradeAs tx {} for msg {} ", val, msg); } setTXState(val); return val; }
@Test public void clientTransactionWithIdleTimeLongerThanTransactionTimeoutIsRemoved() throws Exception { when(msg.getTXOriginatorClient()).thenReturn(mock(InternalDistributedMember.class)); TXStateProxyImpl tx = spy((TXStateProxyImpl) txMgr.getOrSetHostedTXState(txid, msg)); doReturn(true).when(tx).isOverTransactionTimeoutLimit(); txMgr.scheduleToRemoveExpiredClientTransaction(txid); assertTrue(txMgr.isHostedTXStatesEmpty()); }
@Test public void clientTransactionsToBeExpiredAreRemovedAndNotDistributedIfWithNoTimeout() { doReturn(1).when(spyTxMgr).getTransactionTimeToLive(); TXId txId1 = mock(TXId.class); TXId txId2 = mock(TXId.class); TXId txId3 = mock(TXId.class); tx1 = spyTxMgr.getOrSetHostedTXState(txId1, msg); tx2 = spyTxMgr.getOrSetHostedTXState(txId2, msg); Set<TXId> txIds = spy(new HashSet<>()); txIds.add(txId1); doReturn(0).when(spyTxMgr).getTransactionTimeToLive(); when(txIds.iterator()).thenAnswer(new Answer<Iterator<TXId>>() { @Override public Iterator<TXId> answer(InvocationOnMock invocation) throws Throwable { return Arrays.asList(txId1, txId3).iterator(); } }); assertEquals(2, spyTxMgr.getHostedTXStates().size()); spyTxMgr.expireDisconnectedClientTransactions(txIds, false); verify(spyTxMgr, never()).expireClientTransactionsOnRemoteServer(eq(txIds)); verify(spyTxMgr, times(1)).removeHostedTXState(eq(txIds)); verify(spyTxMgr, times(1)).removeHostedTXState(eq(txId1)); verify(spyTxMgr, times(1)).removeHostedTXState(eq(txId3)); assertEquals(tx2, spyTxMgr.getHostedTXStates().get(txId2)); assertEquals(1, spyTxMgr.getHostedTXStates().size()); }
@Test public void testTxStateWithNotFinishedTx() { TXStateProxy tx = txMgr.getOrSetHostedTXState(notCompletedTxid, msg); assertTrue(tx.isInProgress()); }
@Test public void getLockAfterTXStateReplaced() throws InterruptedException { TXStateProxy oldtx = txMgr.getOrSetHostedTXState(txid, msg); assertEquals(oldtx, txMgr.getHostedTXState(txid)); assertTrue(txMgr.getLock(oldtx, txid)); assertNotNull(oldtx); oldtx.getLock().unlock(); TXStateProxy tx = txMgr.getOrSetHostedTXState(txid, msg); assertEquals(tx, oldtx); Thread t1 = new Thread(new Runnable() { @Override public void run() { txMgr.removeHostedTXState(txid); // replace with new TXState txMgr.getOrSetHostedTXState(txid, msg); } }); t1.start(); t1.join(); TXStateProxy curTx = txMgr.getHostedTXState(txid); assertNotNull(curTx); // replaced assertNotEquals(tx, curTx); // after TXStateProxy replaced, getLock will not get assertFalse(txMgr.getLock(tx, txid)); }
@Override public void run() { tx1 = txMgr.getHostedTXState(txid); assertNull(tx1); tx1 = txMgr.getOrSetHostedTXState(txid, msg); assertNotNull(tx1); assertTrue(txMgr.getLock(tx1, txid)); latch.countDown(); await() .until(() -> tx1.getLock().hasQueuedThreads()); txMgr.removeHostedTXState(txid); tx2 = txMgr.getOrSetHostedTXState(txid, msg); assertNotNull(tx2); assertTrue(txMgr.getLock(tx2, txid)); tx2.getLock().unlock(); tx1.getLock().unlock(); } });
@Test public void getOrSetHostedTXStateAbleToSetTXStateAndGetLock() { TXStateProxy tx = txMgr.getOrSetHostedTXState(txid, msg); assertNotNull(tx); assertEquals(tx, txMgr.getHostedTXState(txid)); assertTrue(txMgr.getLock(tx, txid)); }
@Test public void getLockAfterTXStateCommitted() throws InterruptedException { TXStateProxy oldtx = txMgr.getOrSetHostedTXState(txid, msg); oldtx.getLock().unlock(); TXStateProxy tx = txMgr.getOrSetHostedTXState(txid, msg); assertEquals(tx, oldtx);
@Test public void getLockAfterTXStateRemoved() throws InterruptedException { TXStateProxy tx = txMgr.getOrSetHostedTXState(txid, msg); assertEquals(tx, txMgr.getHostedTXState(txid)); assertTrue(txMgr.getLock(tx, txid)); assertNotNull(tx); assertTrue(txMgr.getLock(tx, txid)); tx.getLock().unlock(); TXStateProxy oldtx = txMgr.getOrSetHostedTXState(txid, msg); assertEquals(tx, oldtx); Thread t1 = new Thread(new Runnable() { @Override public void run() { txMgr.removeHostedTXState(txid); } }); t1.start(); t1.join(); TXStateProxy curTx = txMgr.getHostedTXState(txid); assertNull(curTx); // after failover command removed the txid from hostedTXState, // getLock should put back the original TXStateProxy assertTrue(txMgr.getLock(tx, txid)); assertEquals(tx, txMgr.getHostedTXState(txid)); tx.getLock().unlock(); }
@Test public void txStateCleanedUpIfRemovedFromHostedTxStatesMap() { tx1 = txMgr.getOrSetHostedTXState(txid, msg); TXStateProxyImpl txStateProxy = (TXStateProxyImpl) tx1; assertNotNull(txStateProxy); assertFalse(txStateProxy.getLocalRealDeal().isClosed()); txMgr.masqueradeAs(tx1); // during TX failover, tx can be removed from the hostedTXStates map by FindRemoteTXMessage txMgr.getHostedTXStates().remove(txid); txMgr.unmasquerade(tx1); assertTrue(txStateProxy.getLocalRealDeal().isClosed()); }
@Test public void txStateNotCleanedupIfNotRemovedFromHostedTxStatesMap() { tx1 = txMgr.getOrSetHostedTXState(txid, msg); TXStateProxyImpl txStateProxy = (TXStateProxyImpl) tx1; assertNotNull(txStateProxy); assertFalse(txStateProxy.getLocalRealDeal().isClosed()); txMgr.masqueradeAs(tx1); txMgr.unmasquerade(tx1); assertFalse(txStateProxy.getLocalRealDeal().isClosed()); }