package org.multiverse.stms.gamma.integration.failureatomicity; import org.junit.Before; import org.junit.Test; import org.multiverse.TestThread; import org.multiverse.api.Txn; import org.multiverse.api.TxnExecutor; import org.multiverse.api.callables.TxnVoidCallable; import org.multiverse.api.exceptions.TooManyRetriesException; import org.multiverse.stms.gamma.GammaStm; import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong; import org.multiverse.stms.gamma.transactions.GammaTxn; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.multiverse.TestUtils.joinAll; import static org.multiverse.api.GlobalStmInstance.getGlobalStmInstance; import static org.multiverse.api.StmUtils.retry; import static org.multiverse.api.TxnThreadLocal.clearThreadLocalTxn; public class TooManyRetriesRollbackTest { private GammaTxnLong modifyRef; private GammaTxnLong retryRef; private volatile boolean finished; private GammaStm stm; @Before public void setUp() { clearThreadLocalTxn(); stm = (GammaStm) getGlobalStmInstance(); modifyRef = new GammaTxnLong(stm); retryRef = new GammaTxnLong(stm); finished = false; } @Test public void test() { NotifyThread notifyThread = new NotifyThread(); notifyThread.start(); try { setAndAwaitUneven(1); fail(); } catch (TooManyRetriesException expected) { } finished = true; assertEquals(0, modifyRef.atomicGet()); joinAll(notifyThread); } public void setAndAwaitUneven(final int value) { TxnExecutor executor = stm.newTxnFactoryBuilder() .setMaxRetries(10) .newTxnExecutor(); executor.execute(new TxnVoidCallable() { @Override public void call(Txn tx) throws Exception { GammaTxn btx = (GammaTxn) tx; modifyRef.getAndSet(btx, value); if (retryRef.get(btx) % 2 == 0) { retry(); } } }); } class NotifyThread extends TestThread { public NotifyThread() { super("NotifyThread"); } @Override public void doRun() throws Exception { TxnExecutor executor = stm.newTxnFactoryBuilder() .newTxnExecutor(); TxnVoidCallable callable = new TxnVoidCallable() { @Override public void call(Txn tx) throws Exception { GammaTxn btx = (GammaTxn) tx; long value = retryRef.get(btx); retryRef.getAndSet(btx, value + 2); } }; while (!finished) { executor.execute(callable); } } } }