package edu.usc.enl.dynamicmeasurement.algorithms.taskhandler; import edu.usc.enl.dynamicmeasurement.algorithms.tasks.Task2; import edu.usc.enl.dynamicmeasurement.algorithms.tasks.taskthread.LoadTrafficTaskMethod; import edu.usc.enl.dynamicmeasurement.algorithms.transform.TrafficTransformer; import edu.usc.enl.dynamicmeasurement.algorithms.transform.TransformHandlerInterface; import edu.usc.enl.dynamicmeasurement.data.FinishPacket; import edu.usc.enl.dynamicmeasurement.model.WildcardPattern; import edu.usc.enl.dynamicmeasurement.process.EpochPacket; import edu.usc.enl.dynamicmeasurement.process.StepPacketUser; 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: 9/2/13 * Time: 10:20 AM <br/> * The class that handles the dynamics of tasks and runs the main loop of DREAM. * It also keeps track of transforms if they come before their task and has profiling data structure */ public abstract class TaskHandler extends StepPacketUser implements TransformHandlerInterface, Profilable { protected final MultiThread multiThread; private final Map<WildcardPattern, TrafficTransformer> currentTransforms = new HashMap<>(); private LatencyProfiler profiler; public TaskHandler() { multiThread = new MultiThread(Util.getSimulationConfiguration().getThreads()); } @Override public void writeProfiles() { if (profiler != null) { profiler.write(); } } @Override public void createProfiler() { profiler = new LatencyProfiler(getClass()); } @Override public void finishProfiler() { if (profiler != null) { profiler.finish(); } } /** * Adds the task, the rejection may happen later at the right time, if the task is dropped before the first measurement * * @param task * @param step */ public void addTask(Task2 task, int step) { //find if I have a transform for that task for (Map.Entry<WildcardPattern, TrafficTransformer> entry : currentTransforms.entrySet()) { if (task.getFilter().match(entry.getKey())) { task.addTransform(entry.getValue()); } } } /** * @return all added tasks even if they are not yet doing any measurement and we are not sure if we accept them. * Why? because we need to read their traces in the simulation. Note that this will result in ignoring the first * second of traces for each task (can we fix this?) */ public abstract Collection<? extends Task2> getTasks(); /** * removes the task from all data structures as if the task finished by user * * @param taskName * @param step */ public abstract void removeTask(String taskName, int step); /** * reun the main control loop * * @param p */ @Override protected void step(EpochPacket p) { profile("ReadTrace"); boolean hasTraceTask = false; for (Task2 task : getTasks()) { if (task.getTraceReader() != null) { LoadTrafficTaskMethod processTaskMethod = task.getProcessTaskMethod(); processTaskMethod.setEpoch(p); multiThread.offer(processTaskMethod); hasTraceTask = true; } } if (hasTraceTask) { multiThread.runJoin(); } } protected void profile(String s) { //just to not write this if every time I want to profile if (profiler != null) { profiler.sequentialRecord(s); } } @Override public void finish(FinishPacket p) { multiThread.finishThreads(); } @Override public void removeTransform(String transformName) { for (Task2 task2 : getTasks()) { task2.removeTransform(transformName); } } /** * The transform can be applied to the tasks that may instantiate later. * * @param t */ @Override public void addTransform(TrafficTransformer t) { currentTransforms.put(t.getFilter(), t); for (Task2 task2 : getTasks()) { if (task2.getFilter().match(t.getFilter())) { task2.addTransform(t); return; } } // System.err.println("Cannot find task for transform " + t + " with filter " + t.getFilter()); } /** * Call this method to force the handler to write any log it has at this time. * Note that writing logs in any place other than this method can cause unpredictable disk delays in the controll loop. * * @param step */ public abstract void writeLog(int step); }