package edu.usc.enl.dynamicmeasurement.floodlight;
import edu.usc.enl.dynamicmeasurement.algorithms.taskhandler.TaskHandler;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.Task2;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.multiswitch.separateallocation.MultiSwitchTask;
import edu.usc.enl.dynamicmeasurement.data.FinishPacket;
import edu.usc.enl.dynamicmeasurement.model.WildcardPattern;
import edu.usc.enl.dynamicmeasurement.model.event.EventRunner;
import edu.usc.enl.dynamicmeasurement.model.monitorpoint.MonitorPoint;
import edu.usc.enl.dynamicmeasurement.process.EpochPacket;
import edu.usc.enl.dynamicmeasurement.util.Util;
import edu.usc.enl.dynamicmeasurement.util.multithread.MultiThread;
import edu.usc.enl.dynamicmeasurement.util.profile.LatencyProfiler;
import edu.usc.enl.dynamicmeasurement.util.profile.Profilable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* User: masoud
* Date: 10/18/13
* Time: 4:00 PM <br/>
* This is the wrapper around the task handler to adapt it for FloodLight.
* The main functionality of this class is make sure the profilers are finished.
* Finding which OpenFlow rules go on which switch based on the mapping of wildcard patterns and switches.
* Lastly, when the controller receives the counts, it updates the wildcard pattern weights
*/
class RuntimeTaskHandler implements Profilable {
private final TaskHandler taskHandler;
private final EventRunner eventRunner;
private final int epochSize;
private LatencyProfiler profiler;
private MultiThread multiThread;
private Map<String, Map<WildcardPattern, WildcardPattern>> tempRuleMap = new HashMap<>();
RuntimeTaskHandler(TaskHandler taskHandler, EventRunner eventRunner, int epochSize) {
this.taskHandler = taskHandler;
this.eventRunner = eventRunner;
this.epochSize = epochSize;
multiThread = new MultiThread(Util.getSimulationConfiguration().getThreads());
}
protected void step(Collection<SwitchData> switches, int epoch) {
if (tempRuleMap.size() == 0) {
for (SwitchData aSwitch : switches) {
tempRuleMap.put(aSwitch.getStringId(), aSwitch.getWorkingRules());
}
}
profile("UpdateMonitors");
updateMonitors();
profile("Step");
taskHandler.forceStep(new EpochPacket(0, epoch));
//get rules
profile("GetRules");
getRules();
profile(null);
}
@Override
public void writeProfiles() {
if (profiler != null) {
profiler.write();
taskHandler.writeProfiles();
for (Task2 task2 : taskHandler.getTasks()) {
Task2.TaskImplementation implementation = task2.getUser().getImplementation();
if (implementation instanceof Profilable) {
((Profilable) implementation).writeProfiles();
}
}
}
}
@Override
public void createProfiler() {
this.profiler = new LatencyProfiler(getClass());
taskHandler.createProfiler();
}
@Override
public void finishProfiler() {
if (profiler != null) {
this.profiler.finish();
taskHandler.finishProfiler();
for (Task2 task2 : taskHandler.getTasks()) {
Task2.TaskImplementation implementation = task2.getUser().getImplementation();
if (implementation instanceof Profilable) {
((Profilable) implementation).finishProfiler();
}
}
}
}
protected Collection<? extends Task2> getTasks() {
return taskHandler.getTasks();
}
public boolean noEvent() {
return eventRunner.isEmpty();
}
protected void profile(String s) {
if (profiler != null) {
profiler.sequentialRecord(s);
}
}
protected void runEvents(int epoch) {
// System.out.println("event runner empty " + eventRunner.isEmpty() + " for epoch " + epoch);
if (!eventRunner.isEmpty()) {
eventRunner.forceStep(new EpochPacket(0, epoch));
}
}
/**
* Find the OpenFlow rules that must be saved at each switch based on the to be monitored prefixes
*/
private void getRules() {
for (Map<WildcardPattern, WildcardPattern> map : tempRuleMap.values()) {
map.clear();
}
for (final Task2 task2 : getTasks()) {
multiThread.offer(new Runnable() {
@Override
public void run() {
MultiSwitchTask task = (MultiSwitchTask) task2;
TCAMAlgorithm hhhAlgorithm = (TCAMAlgorithm) task.getUser().getImplementation();
Collection<WildcardPattern> monitors = hhhAlgorithm.getMonitors();
for (WildcardPattern monitor : monitors) {
for (MonitorPoint monitorPoint : hhhAlgorithm.getWhichSwitch(monitor)) {
tempRuleMap.get(monitorPoint.getStringId()).put(monitor, monitor);
}
}
}
});
}
multiThread.runJoin();
}
/**
* update wildcard patterns using the counters they saved on the switches based on the mapping of the switches and
* prefixes. It warns if it does not find the corresponding rule at the switch where it should be.
* In the first epoch of the task lifetime this warning should be normal.
*/
private void updateMonitors() {
//now for each task get its monitors and try to update its monitors using the counters
for (final Task2 task2 : getTasks()) {
multiThread.offer(new Runnable() {
@Override
public void run() {
MultiSwitchTask task = (MultiSwitchTask) task2;
TCAMAlgorithm hhhAlgorithm = (TCAMAlgorithm) task.getUser().getImplementation();
Collection<WildcardPattern> monitors = hhhAlgorithm.getMonitors();
for (WildcardPattern monitor : monitors) {
for (MonitorPoint monitorPoint : hhhAlgorithm.getWhichSwitch(monitor)) {
Map<WildcardPattern, WildcardPattern> switchStats = tempRuleMap.get(monitorPoint.getStringId() + "");
WildcardPattern patternInSwitch = switchStats.get(monitor);
if (patternInSwitch != null) {
monitor.setWeight(monitor.getWeight() + patternInSwitch.getWeight());
} else {
PeriodicReport.log.warn("Pattern {} not found in switch {}", monitor.toCIDRString(), monitorPoint.getStringId());
}
}
}
}
});
}
multiThread.runJoin();
}
public void finish(int epoch) {
taskHandler.finish(new FinishPacket((epoch + 1) * epochSize + 0));
multiThread.finishThreads();
}
public void writeLogs(int epoch) {
taskHandler.writeLog(epoch);
}
}