package org.infinispan.tx.lockreordering;
import org.infinispan.Cache;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import javax.transaction.TransactionManager;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
/**
* @author Mircea Markus
* @since 5.1
*/
public class StresserThread extends Thread {
private static Log log = LogFactory.getLog(StresserThread.class);
private static final int NUM_TRANSACTIONS = 250;
static final OperationsPerformer PUT_PERFORMER = new OperationsPerformer() {
@Override
public void perform(List keys, Object value, Cache cache) {
for (Object k : keys) {
cache.put(k, value);
}
}
};
static final OperationsPerformer REMOVE_PERFORMER = new OperationsPerformer() {
@Override
public void perform(List keys, Object value, Cache cache) {
for (Object o : keys) {
cache.remove(o);
}
}
};
static final OperationsPerformer PUT_ALL_PERFORMER = new OperationsPerformer() {
@Override
public void perform(List keys, Object value, Cache cache) {
Map toAdd = new LinkedHashMap();
for (Object o : keys) {
toAdd.put(o, value);
}
cache.putAll(toAdd);
}
};
static final OperationsPerformer MIXED_OPS_PERFORMER = new OperationsPerformer() {
@Override
public void perform(List keys, Object value, Cache cache) {
final Random r = new Random();
for (Object o : keys) {
final int op = r.nextInt(3);
switch (op) {
case 0: {
cache.put(o, value);
break;
}
case 1: {
cache.remove(o);
break;
}
case 2: {
cache.putAll(Collections.singletonMap(o, value));
break;
}
}
}
}
};
public final Cache cache;
public final List keys;
public final String value;
public final OperationsPerformer op;
volatile boolean error = false;
private final CyclicBarrier beforeCommit;
public StresserThread(Cache cache, List keys, String value, OperationsPerformer op, CyclicBarrier beforeCommit, String threadName) {
super(threadName);
this.cache = cache;
this.keys = keys;
this.value = value;
this.op = op;
this.beforeCommit = beforeCommit;
}
@Override
public void run() {
TransactionManager tm = cache.getAdvancedCache().getTransactionManager();
for (int i = 0; i < NUM_TRANSACTIONS; i++) {
try {
tm.begin();
op.perform(keys, value, cache);
beforeCommit.await(10, TimeUnit.SECONDS);
tm.commit();
} catch (Throwable t) {
log.error("Exception:", t);
error = true;
return;
}
}
}
public boolean isError() {
return error;
}
public interface OperationsPerformer {
void perform(List keys, Object value, Cache cache);
}
}