/******************************************************************************* * Copyright (c) 2012-2015 INRIA. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Generoso Pagano - initial API and implementation ******************************************************************************/ package fr.inria.soctrace.framesoc.ui.gantt.loaders; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.inria.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent; import fr.inria.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; import fr.inria.linuxtools.tmf.ui.widgets.timegraph.model.TimeLinkEvent; import fr.inria.soctrace.framesoc.ui.gantt.model.IEventDrawer; import fr.inria.soctrace.framesoc.ui.gantt.model.ReducedEvent; import fr.inria.soctrace.framesoc.ui.model.TimeInterval; import fr.inria.soctrace.lib.model.EventProducer; import fr.inria.soctrace.lib.model.utils.ModelConstants.EventCategory; import fr.inria.soctrace.lib.utils.DeltaManager; /** * Default implementation of the Gantt Chart event drawer. * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ public class NoCpuEventDrawer implements IEventDrawer { /** * Interface for reduced event drawers * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ private interface IReducedEventDrawer { /** * Draw a reduced event * * @param e * the reduced event to draw */ void draw(ReducedEvent rs); } // logger private final static Logger logger = LoggerFactory.getLogger(NoCpuEventDrawer.class); // drawers private Map<Integer, IReducedEventDrawer> drawers = new HashMap<Integer, IReducedEventDrawer>(); // current visualized trace data private Map<Integer, EventProducer> producers; // epid, ep private Map<Integer, GanttEntry> rows; // epid, row private ArrayList<TimeGraphEntry> mainItems; private ArrayList<ILinkEvent> linkList; // current time interval private ArrayList<TimeGraphEntry> newRoots; private boolean needRefresh; // stats private int punctualEvents; private int states; private int links; /** * Constructor. */ public NoCpuEventDrawer() { drawers.put(EventCategory.PUNCTUAL_EVENT, new PunctualEventDrawer()); drawers.put(EventCategory.STATE, new StateDrawer()); drawers.put(EventCategory.LINK, new LinkDrawer()); drawers.put(EventCategory.VARIABLE, new VariableDrawer()); rows = new HashMap<>(); mainItems = new ArrayList<>(); linkList = new ArrayList<>(); newRoots = new ArrayList<>(); } @Override public void setProducers(Map<Integer, EventProducer> producers) { this.producers = producers; } @Override public ArrayList<TimeGraphEntry> getNewRootEntries() { return newRoots; } @Override public ArrayList<ILinkEvent> getLinks() { return linkList; } @Override public void release() { mainItems.clear(); linkList.clear(); rows.clear(); punctualEvents = 0; states = 0; links = 0; } @Override public TimeInterval draw(List<ReducedEvent> events) { Assert.isNotNull(producers, "Null producers in event drawer"); newRoots = new ArrayList<>(); needRefresh = false; // draw states, links and events DeltaManager dm = new DeltaManager(); dm.start(); logger.debug("----------------------------------------"); logger.debug("Prepare Gantt Model"); TimeInterval interval = new TimeInterval(Long.MAX_VALUE, Long.MIN_VALUE); for (ReducedEvent ev : events) { drawers.get(ev.category).draw(ev); if (ev.timestamp < interval.startTimestamp) interval.startTimestamp = ev.timestamp; if (ev.timestamp > interval.endTimestamp) interval.endTimestamp = ev.timestamp; } logger.debug(dm.endMessage("End preparing Gantt model")); logger.debug("----------------------------------------"); // update entries start/end times for (TimeGraphEntry entry : mainItems) { getStartTime(entry); getEndTime(entry); } debug(); return interval; } @Override public boolean needRefresh() { return needRefresh; } private void debug() { logger.debug("Punctual Events: " + punctualEvents); logger.debug("States: " + states); logger.debug("Link: " + links); logger.debug("Entries"); // GanttEntry.debug(logger, mainItems); // logger.debug("Links"); // for (ILinkEvent e : linkList) { // logger.debug(e.toString()); // } } public GanttEntry getProducerRow(EventProducer ep) { // get the row for the given producer if (!rows.containsKey(ep.getId())) { rows.put(ep.getId(), getNewEventProducerRow(ep, producers)); } return rows.get(ep.getId()); } private GanttEntry getNewEventProducerRow(EventProducer ep, Map<Integer, EventProducer> eps) { logger.trace("Creating event producer row " + ep.getId() + ", parent " + ep.getParentId()); GanttEntry entry = new GanttEntry(ep.getName(), ep.getId()); if (ep.getParentId() != EventProducer.NO_PARENT_ID) { GanttEntry parentRow = null; // there's a parent if (rows.containsKey(ep.getParentId())) // there is already its row parentRow = rows.get(ep.getParentId()); else { // new parent parentRow = getNewEventProducerRow(eps.get(ep.getParentId()), eps); rows.put(ep.getParentId(), parentRow); } parentRow.addChild(entry); } else { // we are creating a root entry mainItems.add(entry); newRoots.add(entry); } needRefresh = true; return entry; } private long getStartTime(TimeGraphEntry entry) { // leaf if (!entry.hasChildren()) return entry.getStartTime(); // return the min among its start and its sons start long st = entry.getStartTime(); for (TimeGraphEntry e : entry.getChildren()) { st = Math.min(st, getStartTime(e)); } entry.updateStartTime(st); return entry.getStartTime(); } private long getEndTime(TimeGraphEntry entry) { // leaf if (!entry.hasChildren()) return entry.getEndTime(); // return the max among its end and its sons end long st = entry.getEndTime(); for (TimeGraphEntry e : entry.getChildren()) { st = Math.max(st, getEndTime(e)); } entry.updateEndTime(st); return entry.getEndTime(); } /* * D R A W E R S */ private class PunctualEventDrawer implements IReducedEventDrawer { @Override public void draw(ReducedEvent e) { punctualEvents++; GanttEntry producerRow = getProducerRow(producers.get(e.producerId)); producerRow.setProducingEvent(true); producerRow.addEvent(new GanttEvent(producerRow, e.timestamp, 0, e.typeId)); logger.trace("punctual: {}", e.timestamp); } } private class StateDrawer implements IReducedEventDrawer { @Override public void draw(ReducedEvent e) { states++; GanttEntry producerRow = getProducerRow(producers.get(e.producerId)); producerRow.setProducingEvent(true); long duration = e.endTimestamp - e.timestamp; producerRow.addEvent(new GanttEvent(producerRow, e.timestamp, duration, e.typeId)); logger.trace("state: {} {}", e.timestamp, e.endTimestamp); } } private class LinkDrawer implements IReducedEventDrawer { @Override public void draw(ReducedEvent e) { links++; GanttEntry start = getProducerRow(producers.get(e.producerId)); start.setProducingEvent(true); GanttEntry end = getProducerRow(producers.get(e.endProducerId)); end.setProducingEvent(true); linkList.add(new TimeLinkEvent(start, end, e.timestamp, e.endTimestamp - e.timestamp, e.typeId)); logger.trace("link: {} {}", e.timestamp, e.endTimestamp); } } private class VariableDrawer implements IReducedEventDrawer { @Override public void draw(ReducedEvent e) { // NOP } } }