package org.sdnplatform.sync.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.sdnplatform.sync.IStoreClient;
import org.sdnplatform.sync.ISyncService;
import org.sdnplatform.sync.Versioned;
import org.sdnplatform.sync.ISyncService.Scope;
import org.sdnplatform.sync.error.SyncException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.debugcounter.IDebugCounterService;
/**
* A floodlight module that will start up and start doing horrible,
* horrible things to the sync service.
* @author readams
*/
public class SyncTorture implements IFloodlightModule {
protected static final Logger logger =
LoggerFactory.getLogger(SyncTorture.class);
private static final String SYNC_STORE_NAME =
SyncTorture.class.getCanonicalName() + ".torture";
ISyncService syncService;
IDebugCounterService debugCounter;
int numWorkers = 2;
int keysPerWorker = 1024*1024;
int iterations = 0;
int delay = 0;
@Override
public Collection<Class<? extends IFloodlightService>>
getModuleServices() {
return null;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService>
getServiceImpls() {
return null;
}
@Override
public Collection<Class<? extends IFloodlightService>>
getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(ISyncService.class);
l.add(IDebugCounterService.class);
return l;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
syncService = context.getServiceImpl(ISyncService.class);
debugCounter = context.getServiceImpl(IDebugCounterService.class);
try {
syncService.registerStore(SYNC_STORE_NAME, Scope.GLOBAL);
} catch (SyncException e) {
throw new FloodlightModuleException(e);
}
Map<String,String> config = context.getConfigParams(this);
if (config.containsKey("numWorkers")) {
numWorkers = Integer.parseInt(config.get("numWorkers"));
}
if (config.containsKey("keysPerWorker")) {
keysPerWorker = Integer.parseInt(config.get("keysPerWorker"));
}
if (config.containsKey("iterations")) {
iterations = Integer.parseInt(config.get("iterations"));
}
if (config.containsKey("delay")) {
delay = Integer.parseInt(config.get("delay"));
}
}
@Override
public void startUp(FloodlightModuleContext context)
throws FloodlightModuleException {
try {
final IStoreClient<String, TortureValue> storeClient =
syncService.getStoreClient(SYNC_STORE_NAME,
String.class,
TortureValue.class);
for (int i = 0; i < numWorkers; i++) {
Thread thread = new Thread(new TortureWorker(storeClient, i),
"Torture-" + i);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
} catch (Exception e) {
throw new FloodlightModuleException(e);
}
}
protected static class TortureValue {
private String string;
private int integer;
private boolean bool;
public TortureValue() {
super();
}
public TortureValue(String string, int integer, boolean bool) {
super();
this.string = string;
this.integer = integer;
this.bool = bool;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
public int getInteger() {
return integer;
}
public void setInteger(int integer) {
this.integer = integer;
}
public boolean isBool() {
return bool;
}
public void setBool(boolean bool) {
this.bool = bool;
}
}
protected class TortureWorker implements Runnable {
final IStoreClient<String, TortureValue> storeClient;
final int workerId;
final List<TortureValue> values;
public TortureWorker(IStoreClient<String, TortureValue> storeClient,
int workerId) {
super();
this.storeClient = storeClient;
this.workerId = workerId;
values = new ArrayList<TortureValue>();
for (int i = 0; i < keysPerWorker; i++) {
values.add(new TortureValue(workerId+":"+i, 0, true));
}
}
@Override
public void run() {
if (delay > 0) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) { }
}
int i = 0;
while (iterations == 0 || i++ < iterations) {
long start = System.currentTimeMillis();
try {
for (TortureValue v : values) {
Versioned<TortureValue> vv =
storeClient.get(v.getString());
v.setInteger(v.getInteger() + 1);
v.setBool(!v.isBool());
vv.setValue(v);
storeClient.put(v.getString(), vv);
}
} catch (Exception e) {
logger.error("Error in worker: ", e);
}
long iterend = System.currentTimeMillis();
debugCounter.flushCounters();
logger.info("Completed iteration of {} values in {}ms" +
" ({}/s)",
new Object[]{values.size(), (iterend-start),
1000*values.size()/(iterend-start)});
}
}
}
}