package org.multiverse.stms.gamma.transactions.fat; import org.junit.Test; import org.multiverse.api.exceptions.ReadWriteConflict; import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong; import org.multiverse.stms.gamma.transactionalobjects.Tranlocal; import org.multiverse.stms.gamma.transactions.GammaTxnConfig; import static org.junit.Assert.*; import static org.multiverse.TestUtils.assertIsAborted; import static org.multiverse.TestUtils.assertIsActive; import static org.multiverse.stms.gamma.GammaTestUtils.*; public class FatFixedLengthGammaTxn_openForReadTest extends FatGammaTxn_openForReadTest<FatFixedLengthGammaTxn> { @Override protected FatFixedLengthGammaTxn newTransaction() { return new FatFixedLengthGammaTxn(stm); } @Override protected FatFixedLengthGammaTxn newTransaction(GammaTxnConfig config) { return new FatFixedLengthGammaTxn(config); } @Override protected int getMaxCapacity() { return new GammaTxnConfig(stm).maxFixedLengthTransactionSize; } @Test public void richmansConflict_multipleReadsOnSameRef() { GammaTxnLong ref = new GammaTxnLong(stm); GammaTxnConfig config = new GammaTxnConfig(stm) .setMaximumPoorMansConflictScanLength(0); FatFixedLengthGammaTxn tx1 = new FatFixedLengthGammaTxn(config); FatFixedLengthGammaTxn tx2 = new FatFixedLengthGammaTxn(config); FatFixedLengthGammaTxn tx3 = new FatFixedLengthGammaTxn(config); ref.openForRead(tx1, LOCKMODE_NONE); ref.openForRead(tx2, LOCKMODE_NONE); ref.openForRead(tx3, LOCKMODE_NONE); assertSurplus(ref, 3); } @Test public void richmansConflictScan_whenFirstRead() { causeLotsOfConflicts(stm); long initialValue = 10; GammaTxnLong ref = new GammaTxnLong(stm, initialValue); long initialVersion = ref.getVersion(); GammaTxnConfig config = new GammaTxnConfig(stm) .setMaximumPoorMansConflictScanLength(0); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); Tranlocal tranlocal = ref.openForRead(tx, LOCKMODE_NONE); assertNotNull(tranlocal); assertTrue(tranlocal.hasDepartObligation); assertEquals(initialValue, tranlocal.long_value); assertEquals(initialValue, tranlocal.long_oldValue); assertEquals(LOCKMODE_NONE, tranlocal.lockMode); assertEquals(TRANLOCAL_READ, tranlocal.mode); assertSurplus(ref, 1); assertWriteBiased(ref); assertReadonlyCount(ref, 0); assertIsActive(tx); assertTrue(tx.hasReads); assertEquals(stm.getGlobalConflictCounter().count(), tx.localConflictCount); assertVersionAndValue(ref, initialVersion, initialValue); assertRefHasNoLocks(ref); } @Test public void richmansConflictScan_whenUnrealConflict() { GammaTxnConfig config = new GammaTxnConfig(stm) .setMaximumPoorMansConflictScanLength(0); causeLotsOfConflicts(stm); GammaTxnLong ref1 = new GammaTxnLong(stm, 10); long initialValue2 = 10; GammaTxnLong ref2 = new GammaTxnLong(stm, initialValue2); long initialVersion2 = ref2.getVersion(); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); ref1.openForRead(tx, LOCKMODE_NONE); causeLotsOfConflicts(stm); long newConflictCount = stm.getGlobalConflictCounter().count(); Tranlocal tranlocal2 = ref2.openForRead(tx, LOCKMODE_NONE); assertNotNull(tranlocal2); assertTrue(tranlocal2.hasDepartObligation); assertEquals(initialValue2, tranlocal2.long_value); assertEquals(initialValue2, tranlocal2.long_oldValue); assertEquals(LOCKMODE_NONE, tranlocal2.lockMode); assertEquals(TRANLOCAL_READ, tranlocal2.mode); assertSurplus(ref2, 1); assertWriteBiased(ref2); assertReadonlyCount(ref2, 0); assertIsActive(tx); assertTrue(tx.hasReads); assertEquals(newConflictCount, tx.localConflictCount); assertVersionAndValue(ref2, initialVersion2, initialValue2); assertRefHasNoLocks(ref2); } @Test public void richmansConflictScan_whenConflict() { GammaTxnConfig config = new GammaTxnConfig(stm) .setMaximumPoorMansConflictScanLength(0); causeLotsOfConflicts(stm); GammaTxnLong ref1 = new GammaTxnLong(stm, 10); long initialValue2 = 10; GammaTxnLong ref2 = new GammaTxnLong(stm, initialValue2); long initialVersion2 = ref2.getVersion(); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); ref1.openForRead(tx, LOCKMODE_NONE); ref1.atomicIncrementAndGet(1); try { ref2.openForRead(tx, LOCKMODE_NONE); fail(); } catch (ReadWriteConflict expected) { } assertSurplus(ref2, 0); assertWriteBiased(ref2); assertReadonlyCount(ref2, 0); assertIsAborted(tx); assertVersionAndValue(ref2, initialVersion2, initialValue2); assertRefHasNoLocks(ref2); } }