package edu.usc.enl.dynamicmeasurement.algorithms.tasks.hhh.flow.multiswitch;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.aggregator.AccuracyAggregator;
import edu.usc.enl.dynamicmeasurement.algorithms.tasks.multitask.multiswitch.tcammultitaskmultiswitch.TCAMMultiSwitchTask;
import edu.usc.enl.dynamicmeasurement.data.ConfigReader;
import edu.usc.enl.dynamicmeasurement.model.WildcardPattern;
import edu.usc.enl.dynamicmeasurement.model.monitorpoint.MonitorPoint;
import edu.usc.enl.dynamicmeasurement.util.Util;
import org.w3c.dom.Element;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: masoud
* Date: 8/22/13
* Time: 5:11 PM <br/>
* This is a special class for joint TCAM configuration and TCAM allocation among tasks.
* I'm not sure even if this works or not
*/
public class MultiTaskMultiSwitchResourceNegotiator {
private Map<TCAMMultiSwitchTask, AccuracyAggregator> tasks;
private final MatrixSet.MatrixMapping<MonitorPoint> mapping;
private final Map<MultiSwitch2, TCAMMultiSwitchTask> algorithmTaskMap;
private final Element accuracyAggregatorElement;
public MultiTaskMultiSwitchResourceNegotiator(Element element) {
Map<String, Element> properties = Util.getChildrenProperties(element, "Property");
accuracyAggregatorElement = properties.get("AccuracyAggregator");
mapping = new MatrixSet.MatrixMapping<>();
mapping.addAll(Util.getNetwork().getMonitorPoints());
algorithmTaskMap = new HashMap<>();
}
public Collection<MonitorPoint> getMonitorPoints() {
return mapping;
}
public double findCandidateSiblings(MultiSwitch2 multiSwitch, Set<MonitorPoint> toFreeMonitorPoints, double benefit,
MultiSwitchWildcardPattern maxEntry) {
TCAMMultiSwitchTask task = algorithmTaskMap.get(multiSwitch);
List<SetIdentifier> solution = new ArrayList<>();
//first find tasks that used resources on the toFreeMonitorPoints
MatrixSet<MonitorPoint> toFreeMonitorPoints2 = ((MatrixSet<MonitorPoint>) toFreeMonitorPoints).clone();
List<TCAMMultiSwitchTask> candidateTasks;
if (tasks.get(task).getAccuracy() == 0) {
candidateTasks = new LinkedList<>();
candidateTasks.add(task);
} else {
candidateTasks = getCandidateTasks(toFreeMonitorPoints2);
}
//now for each task find set of siblings that match criteria
Map<SetIdentifier, Set<MonitorPoint>> sets = new HashMap<>();
Map<SetIdentifier, Double> costs = new HashMap<>();
prepare(task, benefit, toFreeMonitorPoints2, candidateTasks, sets, costs);
if (sets.isEmpty()) {
//as maxes are sorted we cannot find any candidates from now on
return -1;
}
solution.clear();
double cost = new SubSetCoverSolver<MonitorPoint>().solve(toFreeMonitorPoints, sets, costs, solution);
if (cost >= 0 && cost < benefit) {
return commit(task, solution, cost, maxEntry, toFreeMonitorPoints2); //use toFreeMonitorPoints2 as the other should be empty by now
}
return 0;
}
private void prepare(TCAMMultiSwitchTask task, double benefit, MatrixSet<MonitorPoint> toFreeMonitorPoints2,
List<TCAMMultiSwitchTask> candidateTasks, Map<SetIdentifier, Set<MonitorPoint>> sets, Map<SetIdentifier, Double> costs) {
for (TCAMMultiSwitchTask candidateTask : candidateTasks) {
double coef;
if (task.equals(candidateTask)) {
coef = 1;
//to skip the case that accuracy is 0 but it is the same task.
// Note the cases with 0 accuracy and different tasks has been filtered before in the candidatetasks list
} else {
coef = task.getThreshold() * tasks.get(task).getAccuracy() / candidateTask.getThreshold() / tasks.get(candidateTask).getAccuracy();
}
Map<WildcardPattern, MultiSwitchWildcardPattern> internalNodes = candidateTask.getMultiSwitch().internalNodes;
for (Map.Entry<WildcardPattern, MultiSwitchWildcardPattern> entry : internalNodes.entrySet()) {
MultiSwitchWildcardPattern mswp = entry.getValue();
//criteria should also depend on threshold and precision difference!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (((MatrixSet<MonitorPoint>) mswp.getMonitorPoints()).getSimilarity(toFreeMonitorPoints2) > 0) {
if (mswp.getCost() * coef < benefit) {
SetIdentifier key = new SetIdentifier(entry.getKey(), candidateTask);
sets.put(key, Util.cloneSet(mswp.getInternalCommonSet()));
costs.put(key, mswp.getCost());
}
}
}
}
}
private double commit(TCAMMultiSwitchTask task, List<SetIdentifier> solution, double cost, MultiSwitchWildcardPattern maxEntry, Set<MonitorPoint> toFreeMonitorPoints) {
Map<TCAMMultiSwitchTask, List<WildcardPattern>> taskMergedWildcardPatterns = new HashMap<>();
for (SetIdentifier setIdentifier : solution) {
TCAMMultiSwitchTask helpfulTask = setIdentifier.getTask();
// if (helpfulTask!=task){
// System.out.println();
// }
List<WildcardPattern> list = taskMergedWildcardPatterns.get(helpfulTask);
if (list == null) {
list = new LinkedList<>();
taskMergedWildcardPatterns.put(helpfulTask, list);
}
list.add(setIdentifier.getWildcardPattern());
//update capacity
Set<MonitorPoint> useFulMonitorPoints = setIdentifier.getUsefulMonitorPoints();
for (MonitorPoint useFulMonitorPoint : useFulMonitorPoints) {
useFulMonitorPoint.decCapacity();
}
}
for (MonitorPoint toFreeMonitorPoint : toFreeMonitorPoints) {
toFreeMonitorPoint.incCapacity();
}
//commit max
task.getMultiSwitch().commitDivide(maxEntry);
//commit merging //may be in multiple tasks
for (Map.Entry<TCAMMultiSwitchTask, List<WildcardPattern>> entry : taskMergedWildcardPatterns.entrySet()) {
entry.getKey().getMultiSwitch().commitMerge(entry.getValue());
}
return cost;
}
private List<TCAMMultiSwitchTask> getCandidateTasks(MatrixSet<MonitorPoint> toFreeMonitorPoints2) {
List<TCAMMultiSwitchTask> candidateTasks = new LinkedList<>();
for (Map.Entry<TCAMMultiSwitchTask, AccuracyAggregator> entry : tasks.entrySet()) {
if (entry.getKey().usedResourceOn(toFreeMonitorPoints2) && entry.getValue().getAccuracy() > 0) {
candidateTasks.add(entry.getKey());
}
}
return candidateTasks;
}
private MatrixSet<MonitorPoint> getMatrixSet(Set<MonitorPoint> toFreeMonitorPoints) {
MatrixSet<MonitorPoint> toFreeMonitorPoints2;
if (toFreeMonitorPoints instanceof MatrixSet) {
toFreeMonitorPoints2 = (MatrixSet<MonitorPoint>) toFreeMonitorPoints;
} else {
toFreeMonitorPoints2 = new MatrixSet<>(mapping);
toFreeMonitorPoints2.addAll(toFreeMonitorPoints);
}
return toFreeMonitorPoints2;
}
public void initialize(Set<TCAMMultiSwitchTask> TCAMMultiSwitchTasks) {
try {
algorithmTaskMap.clear();
for (TCAMMultiSwitchTask task : TCAMMultiSwitchTasks) {
AccuracyAggregator accuracyAggregator = (AccuracyAggregator) Class.forName(accuracyAggregatorElement.getAttribute(ConfigReader.PROPERTY_VALUE)).
getConstructor(Element.class).newInstance(accuracyAggregatorElement);
tasks.put(task, accuracyAggregator);
algorithmTaskMap.put(task.getMultiSwitch(), task);
task.getMultiSwitch().setResourceNegotiator(this);
}
//Assign capacity of monitorpoints for each task, do equal share
//find the number of tasks per monitor point
Map<MonitorPoint, Integer> monitorPointTaskNumMap = new HashMap<>();
Map<MonitorPoint, Integer> capacities = new HashMap<>();
for (MonitorPoint monitorPoint : mapping) {
monitorPointTaskNumMap.put(monitorPoint, 0);
capacities.put(monitorPoint, monitorPoint.getCapacity());
}
for (TCAMMultiSwitchTask task : tasks.keySet()) {
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
monitorPointTaskNumMap.put(monitorPoint, monitorPointTaskNumMap.get(monitorPoint) + 1);
}
}
for (TCAMMultiSwitchTask task : tasks.keySet()) {
for (MonitorPoint monitorPoint : task.getMonitorPoints()) {
monitorPoint.setCapacity(capacities.get(monitorPoint) / monitorPointTaskNumMap.get(monitorPoint));
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
e.printStackTrace();
}
}
public void allocate(Set<TCAMMultiSwitchTask> TCAMMultiSwitchTasks) {
//nothing to do as tasks take resources during the update step
}
private class SetIdentifier implements SubSetCoverSolver.DetailSolution {
private final WildcardPattern wildcardPattern;
private final TCAMMultiSwitchTask task;
private Set<MonitorPoint> usefulMonitorPoints;
private SetIdentifier(WildcardPattern wildcardPattern, TCAMMultiSwitchTask task) {
this.wildcardPattern = wildcardPattern;
this.task = task;
}
private Set<MonitorPoint> getUsefulMonitorPoints() {
return usefulMonitorPoints;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SetIdentifier that = (SetIdentifier) o;
if (!task.equals(that.task)) return false;
if (!wildcardPattern.equals(that.wildcardPattern)) return false;
return true;
}
@Override
public int hashCode() {
int result = wildcardPattern.hashCode();
result = 31 * result + task.hashCode();
return result;
}
private WildcardPattern getWildcardPattern() {
return wildcardPattern;
}
private TCAMMultiSwitchTask getTask() {
return task;
}
@Override
public void setUsefulFor(Set monitorPoints, double avgCost) {
this.usefulMonitorPoints = ((Set<MonitorPoint>) monitorPoints);
}
}
@Override
public String toString() {
return "Multi_Multi_TCAM";
}
}