package org.multiverse.stms.gamma.transactionalobjects.txnref;
import org.junit.Before;
import org.junit.Test;
import org.multiverse.TestThread;
import org.multiverse.stms.gamma.GammaConstants;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnRef;
import org.multiverse.stms.gamma.transactionalobjects.Tranlocal;
import org.multiverse.stms.gamma.transactions.GammaTxn;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.multiverse.TestUtils.*;
public class GammaTxnRef_consistentLoadStressTest implements GammaConstants {
private GammaStm stm;
private volatile boolean stop;
private GammaTxnRef ref;
private final AtomicLong inconsistencyCount = new AtomicLong();
@Before
public void setUp() {
stm = new GammaStm();
stop = false;
ref = new GammaTxnRef(stm, new Long(VERSION_UNCOMMITTED + 1));
}
@Test
public void test() {
int readThreadCount = 10;
ReadThread[] readThreads = new ReadThread[readThreadCount];
for (int k = 0; k < readThreads.length; k++) {
readThreads[k] = new ReadThread(k);
}
int writerCount = 2;
UpdateThread[] updateThreads = new UpdateThread[writerCount];
for (int k = 0; k < updateThreads.length; k++) {
updateThreads[k] = new UpdateThread(k);
}
startAll(readThreads);
startAll(updateThreads);
sleepMs(60 * 1000);
stop = true;
joinAll(readThreads);
joinAll(writerCount);
assertEquals(0, inconsistencyCount.get());
}
class ReadThread extends TestThread {
public ReadThread(int id) {
super("ReadThread-" + id);
}
@Override
public void doRun() throws Exception {
int k = 0;
GammaTxn tx = stm.newDefaultTxn();
Tranlocal tranlocal = new Tranlocal();
while (!stop) {
boolean success = ref.load(tx, tranlocal, LOCKMODE_NONE, 100, true);
if (success) {
Long v = (Long) tranlocal.ref_value;
if (tranlocal.version != v.longValue()) {
inconsistencyCount.incrementAndGet();
System.out.println("Inconsistency detected");
}
if (tranlocal.hasDepartObligation) {
ref.departAfterReading();
}
}
k++;
if (k % 100000 == 0) {
System.out.printf("%s is at %s\n", getName(), k);
}
}
}
}
class UpdateThread extends TestThread {
public UpdateThread(int id) {
super("UpdateThread-" + id);
}
@Override
public void doRun() throws Exception {
int k = 0;
while (!stop) {
int arriveStatus = ref.arriveAndLock(1, LOCKMODE_EXCLUSIVE);
if (arriveStatus == FAILURE) {
continue;
}
Long value = ref.version + 1;
ref.ref_value = value;
ref.version = value;
ref.departAfterUpdateAndUnlock();
k++;
if (k % 100000 == 0) {
System.out.printf("%s is at %s\n", getName(), k);
}
}
}
}
}