package edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.multiswitch.separateallocation;
import edu.usc.enl.dynamicmeasurement.algorithms.taskhandler.TaskHandler;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.Task2;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.TaskEventPublisher;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.aggregator.AccuracyAggregator;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.multiswitch.separateallocation.globaldrop.GlobalDrop;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.singleswitch.resourceallocation.MultiTaskResourceControl;
import edu.usc.enl.dynamicmeasurement.data.ConfigReader;
import edu.usc.enl.dynamicmeasurement.data.DataPacket;
import edu.usc.enl.dynamicmeasurement.data.FinishPacket;
import edu.usc.enl.dynamicmeasurement.model.monitorpoint.MonitorPoint;
import edu.usc.enl.dynamicmeasurement.process.EpochPacket;
import edu.usc.enl.dynamicmeasurement.util.ControlledBufferWriter;
import edu.usc.enl.dynamicmeasurement.util.Util;
import org.w3c.dom.Element;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: masoud
* Date: 9/20/13
* Time: 6:13 PM
*/
public class SeparateMultiTaskMultiSwitchTaskHandler extends TaskHandler implements Observer {
protected final ControlledBufferWriter logWriter;
private final Element localAccuracyAggregatorElement;
private final Element globalAccuracyAggregatorElement;
private final int updateInterval;
private final ControlledBufferWriter shareWriter;
protected Collection<MultiSwitchTask> acceptedTasks;
private Map<MonitorPoint, MonitorPointData> monitorPoints;
private List<Task2> toAddTasks = new ArrayList<>();
private Map<String, Task2> forParentTasks = new HashMap<>();
private GlobalDrop globalDrop;
private boolean debugResourceAllocation = false;
private Set<Task2> toDropTasks = Collections.synchronizedSet(new HashSet<Task2>());
public SeparateMultiTaskMultiSwitchTaskHandler(Element element) throws Exception {
super();
Map<String, Element> properties = Util.getChildrenProperties(element, "Property");
localAccuracyAggregatorElement = properties.get("AccuracyAggregator");
globalAccuracyAggregatorElement = properties.get("GlobalAccuracyAggregator");
Element resourceControlElement = properties.get("ResourceControl");
this.updateInterval = Integer.parseInt(properties.get("UpdateInterval").getAttribute(ConfigReader.PROPERTY_VALUE));
globalDrop = (GlobalDrop) Class.forName(properties.get("GlobalDrop").
getAttribute(ConfigReader.PROPERTY_VALUE)).getConstructor(Element.class, SeparateMultiTaskMultiSwitchTaskHandler.class).newInstance(properties.get("GlobalDrop"), this);
logWriter = Util.getNewWriter(Util.getRootFolder() + "/resource.log", !debugResourceAllocation);
acceptedTasks = new ArrayList<>();
monitorPoints = new HashMap<>();
for (MonitorPoint monitorPoint : Util.getNetwork().getMonitorPoints()) {
MultiTaskResourceControl resourceControl = (MultiTaskResourceControl) Class.forName(
resourceControlElement.getAttribute(ConfigReader.PROPERTY_VALUE)).getConstructor(Element.class, MonitorPoint.class).
newInstance(resourceControlElement, monitorPoint);
MonitorPointData value = new MonitorPointData(monitorPoint, resourceControl);
value.getEventPublisher().subscribe(this);
monitorPoints.put(monitorPoint, value);
value.resourceControl.setLogWriter(logWriter);
}
this.shareWriter =
Util.getNewWriter(Util.getRootFolder() + "/share.csv");
shareWriter.println("time,task,switch,share,accuracy,accuracy_agg");
}
@Override
protected void step(EpochPacket p) {
super.step(p);
int step = p.getStep();
profile("Report");
// report tasks
// update accuracy aggregates
{
for (MultiSwitchTask task : acceptedTasks) {
task.setStep(step);
multiThread.offer(task.getReportTaskMethod());
}
multiThread.runJoin();
}
for (MultiSwitchTask task : acceptedTasks) {
task.updateStats();
}
profile("Add");
addByDelay(step);
profile("Allocate");
// allocate
globalDrop.update();
if ((step + 1) % updateInterval == 0) {
globalDrop.globalDrop();
allocate();
}
profile("Update_Structure");
{
for (MultiSwitchTask task : acceptedTasks) {
task.setStep(step);
// task.getUpdateTaskMethod().run();
multiThread.offer(task.getUpdateTaskMethod());
}
multiThread.runJoin();
}
profile(null);
}
private void addByDelay(int step) {
for (Task2 toAddTask : toAddTasks) {
addTask2(toAddTask, step);
}
toAddTasks.clear();
}
public void writeLog(int step) {
for (MultiSwitchTask task : acceptedTasks) {
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
MultiSwitchTask.SingleSwitchTaskView viewFor = task.getViewFor(monitorPoint);
if (Double.isNaN(viewFor.getAccuracy2())) {
System.out.println("Got Nan estimated accuracy from " + viewFor);
}
shareWriter.print(String.format("%d,%s,%d,%d,%.3f,%.3f",
step, task.getName(), monitorPoint.getIntId(),
viewFor.getResourceShare(), viewFor.getAccuracy2(),
viewFor.getAggregatedAccuracy()));
shareWriter.println();
}
}
shareWriter.flush();
logWriter.flush();
}
protected void allocate() {
toDropTasks.clear();
if (debugResourceAllocation) {
for (Map.Entry<MonitorPoint, MonitorPointData> entry : monitorPoints.entrySet()) {
entry.getValue().getResourceControl().allocate();
}
} else {
for (Map.Entry<MonitorPoint, MonitorPointData> entry : monitorPoints.entrySet()) {
multiThread.offer(entry.getValue().getAllocateTask());
}
multiThread.runJoin();
}
for (Task2 toDropTask : toDropTasks) {
drop((MultiSwitchTask) toDropTask);
}
}
@Override
public void removeTask(String taskName, int step) {
MultiSwitchTask task = (MultiSwitchTask) forParentTasks.get(taskName);
if (task != null) {//otherwise it has been dropped/rejected before
acceptedTasks.remove(task);
doRemove(task);
task.finish(null);
}
}
protected void doRemove(MultiSwitchTask multiSwitchTask) {
for (MonitorPoint monitorPoint : multiSwitchTask.getMonitorPoints()) {
monitorPoints.get(monitorPoint).remove(multiSwitchTask);
}
forParentTasks.remove(multiSwitchTask.getName());
globalDrop.doRemove(multiSwitchTask);
}
@Override
protected void process2(final DataPacket p) {
for (MultiSwitchTask task : acceptedTasks) {
task.process(p);
}
}
@Override
public void finish(FinishPacket p) {
super.finish(p);
for (MultiSwitchTask task : acceptedTasks) {
//if the packet matches task filter, add packet to the task associated user
task.finish(p);
}
acceptedTasks.clear();
forParentTasks.clear();
shareWriter.close();
logWriter.close();
}
@Override
public void addTask(Task2 task2, int step) {
super.addTask(task2, step);
toAddTasks.add(task2);
forParentTasks.put(task2.getName(), task2);
}
private void addTask2(Task2 task2, int step) {
logWriter.println("Add " + task2);
MultiSwitchTask task = (MultiSwitchTask) task2;
try {
//add to every resource control it has traffic from
boolean added = true;
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
boolean result = monitorPoints.get(monitorPoint).resourceControl.addTask(task.getViewFor(monitorPoint));
if (!result) {
added = false;
logWriter.println("task" + task + " rejected on " + monitorPoint);
break;
}
}
if (added) {
AccuracyAggregator globalAccuracyAggregator = (AccuracyAggregator) Class.forName(globalAccuracyAggregatorElement.getAttribute(ConfigReader.PROPERTY_VALUE)).
getConstructor(Element.class).newInstance(globalAccuracyAggregatorElement);
task.setAccuracyAggregator(globalAccuracyAggregator);
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
AccuracyAggregator accuracyAggregator = (AccuracyAggregator) Class.forName(localAccuracyAggregatorElement.getAttribute(ConfigReader.PROPERTY_VALUE)).
getConstructor(Element.class).newInstance(localAccuracyAggregatorElement);
task.setAccuracyAggregator(monitorPoint, accuracyAggregator);
}
acceptedTasks.add(task);
task.update(step); //TODO, for reading traces, the task was in forparenttasks and the parent read the trace for it
} else {
//ok should let the resourceControl free any partial resource it gave to it
doRemove(task);
task.drop();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Collection<MultiSwitchTask> getAcceptedTasks() {
return acceptedTasks;
}
@Override
public Collection<? extends Task2> getTasks() {
return forParentTasks.values();
}
@Override
public void update(Observable o, Object arg) {
TaskEventPublisher.EventWrapper eventWrapper = (TaskEventPublisher.EventWrapper) arg;
MultiSwitchTask task = (MultiSwitchTask) eventWrapper.getTask();
// drop(task);// don't do drop in the middle of allocate just keep the record
//but that allocator relies on dropping this, so just let it see this removed
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
MonitorPointData monitorPointData = monitorPoints.get(monitorPoint);
if (monitorPointData.getResourceControl().equals(eventWrapper.getResourceControl())) {
monitorPointData.remove(task);
break;
}
}
toDropTasks.add(task);
}
public void drop(MultiSwitchTask task) {
if (acceptedTasks.remove(task)) {
logWriter.println("Do drop " + task);
doRemove(task);
task.drop();
}
}
public ControlledBufferWriter getLogWriter() {
return logWriter;
}
private static class MonitorPointData {
private TaskEventPublisher eventPublisher = new TaskEventPublisher();
private MultiTaskResourceControl resourceControl;
private MonitorPoint monitorPoint;
private AllocateThreadMethod allocateTask;
private MonitorPointData(MonitorPoint monitorPoint, MultiTaskResourceControl resourceControl) {
this.monitorPoint = monitorPoint;
this.resourceControl = resourceControl;
resourceControl.setEventPublisher(eventPublisher);
allocateTask = new AllocateThreadMethod(resourceControl);
}
private TaskEventPublisher getEventPublisher() {
return eventPublisher;
}
private MultiTaskResourceControl getResourceControl() {
return resourceControl;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MonitorPointData that = (MonitorPointData) o;
if (monitorPoint != null ? !monitorPoint.equals(that.monitorPoint) : that.monitorPoint != null)
return false;
return true;
}
@Override
public int hashCode() {
return monitorPoint != null ? monitorPoint.hashCode() : 0;
}
public void remove(MultiSwitchTask multiSwitchTask) {
resourceControl.removeTask(multiSwitchTask.getViewFor(monitorPoint));
}
public AllocateThreadMethod getAllocateTask() {
return allocateTask;
}
}
private static class AllocateThreadMethod implements Runnable {
private final MultiTaskResourceControl resourceControl;
private AllocateThreadMethod(MultiTaskResourceControl resourceControl) {
this.resourceControl = resourceControl;
}
@Override
public void run() {
resourceControl.allocate();
}
}
}