/** * 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 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 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)); }