PerformanceMeter pm = perf.createPerformanceMeter(TEST_ID + '#' + testName);
perf.tagAsSummary(pm, "Statistics Analysis: " + testName, Dimension.CPU_TIME);
- if (testTrace == CtfTmfTestTrace.DJANGO_CLIENT) {
+ if (testTrace == CtfTmfTestTrace.DJANGO_CLIENT || testTrace == CtfTmfTestTrace.DJANGO_HTTPD) {
/* Do not show all traces in the global summary */
perf.tagAsGlobalSummary(pm, "Statistics Analysis: " + testName, Dimension.CPU_TIME);
}
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.eclipse.linuxtools.dataviewers.piechart"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
<plugin id="org.eclipse.equinox.launcher.cocoa.macosx.x86_64"/>
<plugin id="org.eclipse.core.net.win32.x86"/>
<plugin id="org.eclipse.core.net.linux.x86"/>
+ <plugin id="org.eclipse.linuxtools.dataviewers.piechart"/>
<plugin id="org.eclipse.tracecompass.tracing.rcp.help"/>
<plugin id="org.sat4j.core"/>
<plugin id="org.sat4j.pb"/>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="tracecompass-e4.5" sequenceNumber="52">
+<?pde version="3.8"?><target name="tracecompass-e4.5" sequenceNumber="53">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.cdt.gnu.dsf.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/mylyn/releases/3.16"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
+<unit id="org.eclipse.linuxtools.dataviewers.feature.feature.group" version="0.0.0"/>
+<repository location="http://download.eclipse.org/linuxtools/update-4.0"/>
+</location>
+<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.swtbot.eclipse.feature.group" version="0.0.0"/>
<unit id="org.eclipse.swtbot.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/technology/swtbot/snapshots"/>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde version="3.8"?><target name="tracecompass-eStaging" sequenceNumber="45">
+<?pde version="3.8"?><target name="tracecompass-eStaging" sequenceNumber="47">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.cdt.gnu.dsf.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/releases/staging"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
+<unit id="org.eclipse.linuxtools.dataviewers.feature.feature.group" version="0.0.0"/>
+<repository location="http://download.eclipse.org/linuxtools/update-4.0"/>
+</location>
+<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.swtbot.eclipse.feature.group" version="0.0.0"/>
<unit id="org.eclipse.swtbot.feature.group" version="0.0.0"/>
<repository location="http://download.eclipse.org/technology/swtbot/snapshots"/>
org.eclipse.ui.navigator,
org.eclipse.ui.navigator.resources,
org.swtchart,
- com.ibm.icu
+ com.ibm.icu,
+ org.eclipse.linuxtools.dataviewers.piechart
Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse.tracecompass.tmf.ui.tests,org.eclipse.tracecompass.tmf.ctf.ui.tests",
org.eclipse.tracecompass.internal.tmf.ui.commands;x-internal:=true,
org.eclipse.tracecompass.internal.tmf.ui.dialogs;x-internal:=true,
org.eclipse.tracecompass.tmf.ui.viewers.events,
org.eclipse.tracecompass.tmf.ui.viewers.events.columns,
org.eclipse.tracecompass.tmf.ui.viewers.events.text,
+ org.eclipse.tracecompass.tmf.ui.viewers.piecharts,
org.eclipse.tracecompass.tmf.ui.viewers.statistics,
org.eclipse.tracecompass.tmf.ui.viewers.statistics.model,
org.eclipse.tracecompass.tmf.ui.viewers.table,
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+/**
+ * Interface used to take control of a {@link TmfPieChartViewer} as part of the
+ * State design pattern. Thus it is closely related with the TmfPieChartViewer
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+interface IPieChartViewerState {
+
+ /**
+ * To be called when the current selection has changed
+ *
+ * @param context
+ * The context in which to apply the changes
+ */
+ void newSelection(final TmfPieChartViewer context);
+
+ /**
+ * To be called when the current selection changes to "empty"
+ *
+ * @param context
+ * The context in which to apply the changes
+ */
+ void newEmptySelection(final TmfPieChartViewer context);
+
+ /**
+ * To be called when there are new global entries to show
+ *
+ * @param context
+ * The context in which to apply the changes
+ */
+ void newGlobalEntries(final TmfPieChartViewer context);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and Implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages file for statistics view strings.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.tmf.ui.viewers.piecharts.messages"; //$NON-NLS-1$
+
+ /**
+ * String shown on top of the time-range selection piechart
+ */
+ public static String TmfStatisticsView_TimeRangeSelectionPieChartName;
+
+ /**
+ * String given to the slice in the piechart containing the too little
+ * slices
+ */
+ public static String TmfStatisticsView_PieChartOthersSliceName;
+
+ /**
+ * String for the top of the global selection piechart
+ */
+ public static String TmfStatisticsView_GlobalSelectionPieChartName;
+
+ /**
+ * The string in the tooltip text of the piecharts
+ */
+ public static String TmfStatisticsView_PieChartToolTipTextName;
+
+ /**
+ * The string in the tooltip text of the piecharts
+ */
+ public static String TmfStatisticsView_PieChartToolTipTextEventCount;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Implementation of the IPieChartViewerState interface to represent the state
+ * of the layout when there is content currently selected.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class PieChartViewerStateContentSelected implements IPieChartViewerState {
+
+ /**
+ * Default constructor
+ *
+ * @param context
+ * The context to apply the changes
+ */
+ public PieChartViewerStateContentSelected(final TmfPieChartViewer context) {
+ if (context.isDisposed()) {
+ return;
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (context) {
+ if (!context.isDisposed()) {
+ context.updateGlobalPieChart();
+ context.updateTimeRangeSelectionPieChart();
+ context.getTimeRangePC().redraw();
+ context.getGlobalPC().getLegend().setPosition(SWT.BOTTOM);
+ context.layout();
+ }
+ }
+ }
+ });
+
+ }
+
+ @Override
+ public void newSelection(final TmfPieChartViewer context) {
+ if (context.isDisposed()) {
+ return;
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (context) {
+ if (!context.isDisposed()) {
+ context.updateTimeRangeSelectionPieChart();
+ context.getTimeRangePC().redraw();
+ context.layout();
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void newEmptySelection(final TmfPieChartViewer context) {
+ context.setCurrentState(new PieChartViewerStateNoContentSelected(context));
+ }
+
+ @Override
+ public void newGlobalEntries(final TmfPieChartViewer context) {
+ // when new global entries, don't show the selection pie-chart anymore
+ context.setCurrentState(new PieChartViewerStateNoContentSelected(context));
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Implementation of the IPieChartViewerState interface to represent the state
+ * of the layout when there is no content currently selected.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class PieChartViewerStateNoContentSelected implements IPieChartViewerState {
+
+ /**
+ * Default constructor
+ *
+ * @param context
+ * The current context
+ */
+ public PieChartViewerStateNoContentSelected(final TmfPieChartViewer context) {
+ if (context.isDisposed()) {
+ return;
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (context) {
+ if (!context.isDisposed()) {
+ // Have to get rid of the time-range PieChart
+ if (context.getTimeRangePC() != null) {
+ if (!context.getTimeRangePC().isDisposed()) {
+ context.getTimeRangePC().dispose();
+ }
+ context.setTimeRangePC(null);
+ }
+
+ context.updateGlobalPieChart();
+ // update the global chart so it takes all the place
+ context.getGlobalPC().getLegend().setPosition(SWT.RIGHT);
+ context.layout();
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void newSelection(final TmfPieChartViewer context) {
+ context.setCurrentState(new PieChartViewerStateContentSelected(context));
+ }
+
+ @Override
+ public void newEmptySelection(final TmfPieChartViewer context) {
+ // do nothing
+ }
+
+ @Override
+ public void newGlobalEntries(final TmfPieChartViewer context) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (context) {
+ if (!context.isDisposed()) {
+ context.updateGlobalPieChart();
+ context.getGlobalPC().redraw();
+ }
+ }
+ }
+ });
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.linuxtools.dataviewers.piechart.PieChart;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
+
+/**
+ * Creates a viewer containing 2 pie charts, one for showing information about
+ * the current selection, and the second one for showing information about the
+ * current time-range selection. It follows the MVC pattern, being a view.
+ *
+ * This class is closely related with the IPieChartViewerState interface
+ * that acts as a state machine for the general layout of the charts.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ *
+ */
+public class TmfPieChartViewer extends Composite {
+
+ /**
+ * The pie chart containing global information about the trace
+ */
+ private PieChart fGlobalPC;
+
+ /**
+ * The name of the piechart containing the statistics about the global trace
+ */
+ private String fGlobalPCname;
+
+ /**
+ * The pie chart containing information about the current time-range
+ * selection
+ */
+ private PieChart fTimeRangePC;
+
+ /**
+ * The name of the piechart containing the statistics about the current
+ * selection
+ */
+ private String fTimeRangePCname;
+
+ /**
+ * The listener added to the charts every time they are created
+ */
+ private Listener fMouseListener;
+
+ /**
+ * The name of the slice containing the too little slices
+ */
+ private String fOthersSliceName;
+
+ /**
+ * Implementation of the State design pattern to reorder the layout
+ * depending on the selection. This variable holds the current state of the
+ * layout.
+ */
+ private IPieChartViewerState fCurrentState;
+
+ /**
+ * Represents the minimum percentage a slice of pie must have in order to be
+ * shown
+ */
+ private static final float MIN_PRECENTAGE_TO_SHOW_SLICE = 0.025F;// 2.5%
+
+ /**
+ * Represents the maximum number of slices of the pie charts. WE don't want
+ * to pollute the viewer with too much slice entries.
+ */
+ private static final int NB_MAX_SLICES = 10;
+
+ /**
+ * The data that has to be presented by the pie charts
+ */
+ private TmfPieChartStatisticsModel fModel = null;
+
+ /**
+ * @param parent
+ * The parent composite that will hold the viewer
+ */
+ public TmfPieChartViewer(Composite parent) {
+ super(parent, SWT.NONE);
+ fGlobalPCname = Messages.TmfStatisticsView_GlobalSelectionPieChartName;
+ fTimeRangePCname = Messages.TmfStatisticsView_TimeRangeSelectionPieChartName;
+ fOthersSliceName = Messages.TmfStatisticsView_PieChartOthersSliceName;
+ initContent();
+ }
+
+ // ------------------------------------------------------------------------
+ // Class methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Called by this class' constructor. Constructs the basic viewer containing
+ * the charts, as well as their listeners
+ */
+ private void initContent() {
+ setLayout(new FillLayout());
+
+ fGlobalPC = null;
+ fTimeRangePC = null;
+
+ // Setup listeners for the tooltips
+ fMouseListener = new Listener() {
+ @Override
+ public void handleEvent(org.eclipse.swt.widgets.Event event) {
+ PieChart pc = (PieChart) event.widget;
+ switch (event.type) {
+ case SWT.MouseMove:
+ int sliceIndex = pc.getSliceIndexFromPosition(0, event.x, event.y);
+ if (sliceIndex < 0) {
+ // mouse is outside the chart
+ pc.setToolTipText(null);
+ break;
+ }
+ float percOfSlice = (float) pc.getSlicePercent(0, sliceIndex);
+ String percent = String.format("%.1f", percOfSlice); //$NON-NLS-1$
+ Long nbEvents = Long.valueOf((long) pc.getSeriesSet().getSeries()[sliceIndex].getXSeries()[0]);
+
+ String text = Messages.TmfStatisticsView_PieChartToolTipTextName + " = " + //$NON-NLS-1$
+ pc.getSeriesSet().getSeries()[sliceIndex].getId() + "\n"; //$NON-NLS-1$
+
+ text += Messages.TmfStatisticsView_PieChartToolTipTextEventCount + " = "//$NON-NLS-1$
+ + nbEvents.toString() + " (" + percent + "%)"; //$NON-NLS-1$ //$NON-NLS-2$
+ pc.setToolTipText(text);
+ return;
+ default:
+ }
+ }
+ };
+ // at creation no content is selected
+ setCurrentState(new PieChartViewerStateNoContentSelected(this));
+ }
+
+ @Override
+ public void dispose() {
+ if (fGlobalPC != null) {
+ fGlobalPC.dispose();
+ }
+ if (fTimeRangePC != null) {
+ fTimeRangePC.dispose();
+ }
+ super.dispose();
+ }
+
+ /**
+ * Updates the data contained in the Global PieChart by using a Map.
+ * Normally, this method is only called by the state machine.
+ */
+ synchronized void updateGlobalPieChart() {
+ if (getGlobalPC() == null) {
+ fGlobalPC = new PieChart(this, SWT.NONE);
+ getGlobalPC().getTitle().setText(fGlobalPCname);
+ getGlobalPC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
+ getGlobalPC().getLegend().setVisible(true);
+ getGlobalPC().getLegend().setPosition(SWT.RIGHT);
+ getGlobalPC().addListener(SWT.MouseMove, fMouseListener);
+ } else if (getGlobalPC().isDisposed() || fModel == null || fModel.getPieChartGlobalModel() == null) {
+ return;
+ }
+
+ Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(true);
+
+ if(totalEventCountForChart == null){
+ return;
+ }
+
+ updatePieChartWithData(fGlobalPC, totalEventCountForChart, MIN_PRECENTAGE_TO_SHOW_SLICE, fOthersSliceName);
+ }
+
+ /**
+ * Updates the data contained in the Time-Range PieChart by using a Map.
+ * Normally, this method is only called by the state machine.
+ */
+ synchronized void updateTimeRangeSelectionPieChart() {
+ if (getTimeRangePC() == null) {
+ fTimeRangePC = new PieChart(this, SWT.NONE);
+ getTimeRangePC().getTitle().setText(fTimeRangePCname);
+ getTimeRangePC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
+ getTimeRangePC().getLegend().setPosition(SWT.BOTTOM);
+ getTimeRangePC().getLegend().setVisible(true);
+ getTimeRangePC().addListener(SWT.MouseMove, fMouseListener);
+ }
+ else if (getTimeRangePC().isDisposed()) {
+ return;
+ }
+
+ Map<String, Long> totalEventCountForChart = getTotalEventCountForChart(false);
+
+ if(totalEventCountForChart == null){
+ return;
+ }
+
+ updatePieChartWithData(fTimeRangePC, totalEventCountForChart, MIN_PRECENTAGE_TO_SHOW_SLICE, fOthersSliceName);
+ }
+
+ /* return the chart-friendly map given by the TmfPieChartStatisticsModel */
+ private Map<String,Long> getTotalEventCountForChart(boolean isGlobal){
+ if(fModel == null){
+ return null;
+ }
+ Map<ITmfTrace, Map<String, Long>> chartModel;
+ if(isGlobal){
+ chartModel = fModel.getPieChartGlobalModel();
+ } else {
+ chartModel = fModel.getPieChartSelectionModel();
+ }
+ if(chartModel == null){
+ return null;
+ }
+
+ Map<String, Long> totalEventCountForChart = new HashMap<>();
+ for(Entry<ITmfTrace, Map<String, Long>> entry : chartModel.entrySet()){
+ Map<String, Long> traceEventCount = entry.getValue();
+ if(traceEventCount == null){
+ continue;
+ }
+ for(Entry<String, Long> event : traceEventCount.entrySet()){
+ if(totalEventCountForChart.containsKey(event.getKey())){
+ totalEventCountForChart.put(event.getKey(), totalEventCountForChart.get(event.getKey()) + event.getValue());
+ } else {
+ totalEventCountForChart.put(event.getKey(), event.getValue());
+ }
+ }
+ }
+
+ return totalEventCountForChart;
+ }
+
+ /**
+ * Reinitializes the charts to their initial state, without any data
+ */
+ synchronized public void reinitializeCharts() {
+ if(isDisposed()){
+ return;
+ }
+
+ if (getGlobalPC() != null && !getGlobalPC().isDisposed()) {
+ getGlobalPC().dispose();
+ }
+ fGlobalPC = new PieChart(this, SWT.NONE);
+ getGlobalPC().getTitle().setText(fGlobalPCname);
+ getGlobalPC().getAxisSet().getXAxis(0).getTitle().setText(""); //Hide the title over the legend //$NON-NLS-1$
+ if (getTimeRangePC() != null && !getTimeRangePC().isDisposed()) {
+ getTimeRangePC().dispose();
+ fTimeRangePC = null;
+ }
+ layout();
+ setCurrentState(new PieChartViewerStateNoContentSelected(this));
+ }
+
+ /**
+ * Function used to update or create the slices of a PieChart to match the
+ * content of a Map passed in parameter. It also provides a facade to use
+ * the PieChart API
+ */
+ private static void updatePieChartWithData(
+ final PieChart chart,
+ final Map<String, Long> slices,
+ final float minimumSizeOfSlice,
+ final String nameOfOthers) {
+
+ List<EventOccurrenceObject> chartValues = new ArrayList<>();
+ Long eventTotal = 0L;
+ for (Entry<String, Long> entry : slices.entrySet()) {
+ eventTotal += entry.getValue();
+ chartValues.add(new EventOccurrenceObject(entry.getKey(), entry.getValue()));
+ }
+
+ // No events in the selection
+ if (eventTotal == 0) {
+ // clear the chart and show "NO DATA"
+
+ return;
+ }
+
+ /*
+ * filter out the event types taking too little space in the chart and
+ * label the whole group together. The remaining slices will be showing
+ */
+ List<EventOccurrenceObject> filteredChartValues = new ArrayList<>();
+ Long othersEntryCount = 0L;
+ int nbSlices = 0;
+ for (EventOccurrenceObject entry : chartValues) {
+ if (entry.getNbOccurence() / eventTotal.floatValue() > minimumSizeOfSlice && nbSlices <= NB_MAX_SLICES) {
+ filteredChartValues.add(entry);
+ nbSlices++;
+ } else {
+ othersEntryCount += entry.getNbOccurence();
+ }
+ }
+
+ Collections.sort(filteredChartValues);
+
+ // Add the "Others" slice in the pie if its not empty
+ if (othersEntryCount != 0) {
+ filteredChartValues.add(new EventOccurrenceObject(nameOfOthers, othersEntryCount));
+ }
+
+ // put the entries in the chart and add their percentage
+ double[][] tempValues = new double[filteredChartValues.size()][1];
+ String[] tempNames = new String[filteredChartValues.size()];
+ int index = 0;
+ for (EventOccurrenceObject entry : filteredChartValues) {
+ tempValues[index][0] = entry.getNbOccurence();
+ tempNames[index] = entry.getName();
+ index++;
+ }
+
+ chart.addPieChartSeries(tempNames, tempValues);
+ }
+
+ /**
+ * Refresh this viewer
+ * @param refreshGlobal if we have to refresh the global piechart
+ * @param refreshSelection if we have to refresh the selection piechart
+ */
+ public synchronized void refresh(boolean refreshGlobal, boolean refreshSelection) {
+ if(fModel == null){
+ reinitializeCharts();
+ } else {
+ if(refreshGlobal){
+ /* will update the global pc */
+ getCurrentState().newGlobalEntries(this);
+ }
+
+ if(refreshSelection){
+ // Check if the selection is empty
+ int nbEventsType = 0;
+ Map<String, Long> selectionModel = getTotalEventCountForChart(false);
+ for (Long l : selectionModel.values()) {
+ if(l != 0){
+ nbEventsType++;
+ }
+ }
+
+ // Check if the selection is empty or if
+ // there is enough event types to show in the piecharts
+ if (nbEventsType < 2) {
+ getCurrentState().newEmptySelection(this);
+ } else {
+ getCurrentState().newSelection(this);
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return the global piechart
+ */
+ synchronized PieChart getGlobalPC() {
+ return fGlobalPC;
+ }
+
+ /**
+ * @return the time-range selection piechart
+ */
+ synchronized PieChart getTimeRangePC() {
+ return fTimeRangePC;
+ }
+
+ /**
+ * @return the current state of the viewer
+ */
+ synchronized IPieChartViewerState getCurrentState() {
+ return fCurrentState;
+ }
+
+ // ------------------------------------------------------------------------
+ // Setters
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return the model
+ */
+ public TmfPieChartStatisticsModel getModel() {
+ return fModel;
+ }
+
+ /**
+ * @param model the model to set
+ */
+ public void setInput(TmfPieChartStatisticsModel model) {
+ fModel = model;
+ }
+
+ /**
+ * Normally, this method is only called by the state machine
+ *
+ * @param newChart
+ * the new PieChart
+ */
+ public synchronized void setTimeRangePC(PieChart newChart) {
+ fTimeRangePC = newChart;
+ }
+
+ /**
+ * Setter method for the state.
+ *
+ * @param newState
+ * The new state of the viewer Normally only called by classes
+ * implementing the IPieChartViewerState interface.
+ */
+ public synchronized void setCurrentState(final IPieChartViewerState newState) {
+ fCurrentState = newState;
+ }
+
+ /**
+ * Nested class used to handle and sort more easily the pair (Name, Number
+ * of occurrences)
+ *
+ * @author Alexis Cabana-Loriaux
+ */
+ private static class EventOccurrenceObject implements Comparable<EventOccurrenceObject> {
+
+ private String fName;
+
+ private Long fNbOccurrences;
+
+ EventOccurrenceObject(String name, Long nbOccurences) {
+ this.fName = name;
+ this.fNbOccurrences = nbOccurences;
+ }
+
+ @Override
+ public int compareTo(EventOccurrenceObject other) {
+ // descending order
+ return -Long.compare(this.getNbOccurence(), other.getNbOccurence());
+ }
+
+ public String getName() {
+ return fName;
+ }
+
+ public Long getNbOccurence() {
+ return fNbOccurrences;
+ }
+ }
+}
--- /dev/null
+###############################################################################
+# Copyright (c) 2015 Ericsson
+#
+# 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:
+# Ericsson - Initial API and implementation
+###############################################################################
+
+TmfStatisticsView_GlobalSelectionPieChartName=Global
+TmfStatisticsView_TimeRangeSelectionPieChartName=Events in selection
+TmfStatisticsView_PieChartOthersSliceName=Others
+TmfStatisticsView_PieChartToolTipTextName=Name
+TmfStatisticsView_PieChartToolTipTextEventCount=Event Count
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Alexis Cabana-Loriaux - Initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.TmfPieChartViewer;
+
+/**
+ * This class contains the model shown by the {@link TmfPieChartViewer}.
+ *
+ * @author Alexis Cabana-Loriaux
+ * @since 2.0
+ */
+public class TmfPieChartStatisticsModel {
+
+ /**
+ * The model for the PieChart viewer. For each chart, a trace has a group of
+ * events and an associated count
+ */
+ private final Map<ITmfTrace, Map<String, Long>> fPieChartGlobalModel = new ConcurrentHashMap<>();
+ private final Map<ITmfTrace, Map<String, Long>> fPieChartSelectionModel = new ConcurrentHashMap<>();
+
+ /**
+ * Default constructor
+ */
+ public TmfPieChartStatisticsModel() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Class Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Clean out the entire model
+ */
+ public void clear() {
+ fPieChartGlobalModel.clear();
+ fPieChartSelectionModel.clear();
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters and setter
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return the model to be applied to the global piechart
+ */
+ public Map<ITmfTrace, Map<String, Long>> getPieChartGlobalModel() {
+ return fPieChartGlobalModel;
+ }
+
+ /**
+ * @return the model to be applied to the global piechart
+ */
+ public Map<ITmfTrace, Map<String, Long>> getPieChartSelectionModel() {
+ return fPieChartSelectionModel;
+ }
+
+ /**
+ * Method used to set the model of one of the pie chart
+ *
+ * @param isGlobal if the model to update is global or selection piechart
+ * @param jobTrace the trace
+ * @param eventsPerType the map with pairs (Event, count)
+ */
+ public void setPieChartTypeCount(boolean isGlobal, ITmfTrace jobTrace, Map<String, Long> eventsPerType) {
+ Map<ITmfTrace,Map<String, Long>> chartModel;
+ if(isGlobal){
+ chartModel = fPieChartGlobalModel;
+ } else {
+ chartModel = fPieChartSelectionModel;
+ }
+
+ chartModel.put(jobTrace, eventsPerType);
+ }
+}
*/
public static String TmfStatisticsView_UnknownTraceName;
+ /**
+ * String shown on top of the time-range selection piechart
+ *
+ * @since 2.0
+ */
+ public static String TmfStatisticsView_TimeRangeSelectionPieChartName;
+
+ /**
+ * String given to the slice in the piechart containing the too little
+ * slices
+ * @since 2.0
+ */
+ public static String TmfStatisticsView_PieChartOthersSliceName;
+
+ /**
+ * String for the top of the global selection piechart
+ * @since 2.0
+ */
+ public static String TmfStatisticsView_GlobalSelectionPieChartName;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Mathieu Denis - Initial API and implementation
+ * Alexis Cabana-Loriaux - Extract the class in a compilation unit
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.ui.viewers.statistics;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.tmf.core.statistics.ITmfStatistics;
+import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
+import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
+import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
+import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
+
+/**
+ * Class used to update the Statistics view. Normally, it should only be used by
+ * this class
+ *
+ * @author Mathieu Denis
+ */
+class StatisticsUpdateJob extends Job {
+
+ private final ITmfTrace fJobTrace;
+ private final boolean fIsGlobal;
+ private final TmfStatisticsModule fStatsMod;
+ private final TmfStatisticsViewer fViewer;
+
+ /**
+ * The delay (in ms) between each update in live-reading mode
+ */
+ private static final long LIVE_UPDATE_DELAY = 1000;
+
+ /**
+ * Timestamp scale used for all statistics (nanosecond)
+ */
+ private static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
+ private TmfTimeRange fTimerange;
+
+ /**
+ * @param name
+ * The name of the working job
+ * @param trace
+ * The trace to query
+ * @param isGlobal
+ * If the query is for the global time-range or a selection
+ * time-range
+ * @param timerange
+ * The timerange of
+ * @param statsMod
+ * The statistics module of the trace
+ * @param viewer
+ * The viewer to update
+ */
+ public StatisticsUpdateJob(String name, ITmfTrace trace, boolean isGlobal, TmfTimeRange timerange, TmfStatisticsModule statsMod, TmfStatisticsViewer viewer) {
+ super(name);
+ fJobTrace = trace;
+ fIsGlobal = isGlobal;
+ fTimerange = timerange;
+ fStatsMod = statsMod;
+ fViewer = viewer;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+
+ /* Wait until the analysis is ready to be queried */
+ fStatsMod.waitForInitialization();
+ ITmfStatistics stats = fStatsMod.getStatistics();
+ if (stats == null) {
+ /* It should have worked, but didn't */
+ throw new IllegalStateException();
+ }
+
+ /*
+ * TODO Eventually this could be exposed through the
+ * TmfStateSystemAnalysisModule directly.
+ */
+ ITmfStateSystem ss = fStatsMod.getStateSystem(TmfStatisticsEventTypesModule.ID);
+ if (ss == null) {
+ /*
+ * It should be instantiated after the
+ * statsMod.waitForInitialization() above.
+ */
+ throw new IllegalStateException();
+ }
+
+ /*
+ * Periodically update the statistics while they are being built (or, if
+ * the back-end is already completely built, it will skip over the
+ * while() immediately.
+ */
+ long start = 0;
+ long end = 0;
+ boolean finished = false;
+ do {
+ /* This model update is done every second */
+ if (monitor.isCanceled()) {
+ fViewer.removeFromJobs(fIsGlobal, fJobTrace);
+ return Status.CANCEL_STATUS;
+ }
+ finished = ss.waitUntilBuilt(LIVE_UPDATE_DELAY);
+ TmfTimeRange localtimeRange = fTimerange;
+ /*
+ * The generic statistics are stored in nanoseconds, so we must make
+ * sure the time range is scaled correctly.
+ */
+ start = localtimeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
+ end = localtimeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
+
+ Map<String, Long> map = stats.getEventTypesInRange(start, end);
+ updateStats(map);
+ } while (!finished);
+
+ /* Query one last time for the final values */
+ Map<String, Long> map = stats.getEventTypesInRange(start, end);
+ updateStats(map);
+ fViewer.refreshPieCharts(fIsGlobal, !fIsGlobal);
+ /*
+ * Remove job from map so that new range selection updates can be
+ * processed.
+ */
+ fViewer.removeFromJobs(fIsGlobal, fJobTrace);
+ return Status.OK_STATUS;
+ }
+
+ /*
+ * Update the tree for a given trace
+ */
+ private void updateStats(Map<String, Long> eventsPerType) {
+
+ final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(fViewer.getTreeID());
+ if (statsData == null) {
+ /* The stat tree has been disposed, abort mission. */
+ return;
+ }
+
+ Map<String, Long> map = eventsPerType;
+ String name = fJobTrace.getName();
+
+ /**
+ * <pre>
+ * "Global", "partial", "total", etc., it's all very confusing...
+ *
+ * The base view shows the total count for the trace and for
+ * each even types, organized in columns like this:
+ *
+ * | Global | Time range |
+ * trace name | A | B |
+ * Event Type | | |
+ * <event 1> | C | D |
+ * <event 2> | ... | ... |
+ * ... | | |
+ *
+ * Here, we called the cells like this:
+ * A : GlobalTotal
+ * B : TimeRangeTotal
+ * C : GlobalTypeCount(s)
+ * D : TimeRangeTypeCount(s)
+ * </pre>
+ */
+
+ /* Fill in an the event counts (either cells C or D) */
+ for (Map.Entry<String, Long> entry : map.entrySet()) {
+ statsData.setTypeCount(name, entry.getKey(), fIsGlobal, entry.getValue());
+ }
+
+ /*
+ * Calculate the totals (cell A or B, depending if isGlobal). We will
+ * use the results of the previous request instead of sending another
+ * one.
+ */
+ long globalTotal = 0;
+ for (long val : map.values()) {
+ globalTotal += val;
+ }
+ /* Update both the tree model and the piechart model */
+ statsData.setTotal(name, fIsGlobal, globalTotal);
+ TmfPieChartStatisticsModel model = fViewer.getPieChartModel();
+ if (model != null) {
+ model.setPieChartTypeCount(fIsGlobal, fJobTrace, eventsPerType);
+ }
+ /* notify that the viewer needs to be refreshed */
+ fViewer.modelComplete(fIsGlobal);
+ }
+}
import java.util.List;
import java.util.Map;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
-import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
-import org.eclipse.tracecompass.tmf.core.statistics.ITmfStatistics;
-import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
-import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.TmfPieChartViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
import org.eclipse.tracecompass.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
*/
public class TmfStatisticsViewer extends TmfViewer {
- /** Timestamp scale used for all statistics (nanosecond) */
- private static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
-
- /** The delay (in ms) between each update in live-reading mode */
- private static final long LIVE_UPDATE_DELAY = 1000;
-
/** The actual tree viewer to display */
private TreeViewer fTreeViewer;
- /** The statistics tree linked to this viewer */
- private TmfStatisticsTree fStatisticsData;
-
/** Update range synchronization object */
private final Object fStatisticsRangeUpdateSyncObj = new Object();
+ /** The statistics tree linked to this viewer */
+ private TmfStatisticsTree fStatisticsData;
+
/** The trace that is displayed by this viewer */
private ITmfTrace fTrace;
private final Map<ITmfTrace, Job> fUpdateJobsPartial = new HashMap<>();
private final Map<ITmfTrace, Job> fUpdateJobsGlobal = new HashMap<>();
- private TmfTimeRange fTimeRange;
+ private TmfPieChartViewer fPieChartViewer;
+
+ private SashForm fSash;
- private TmfTimeRange fTimeRangePartial;
+ private TmfPieChartStatisticsModel fPieChartModel;
/**
* Create a basic statistics viewer. To be used in conjunction with
// Clean the model for this viewer
TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
+ fPieChartViewer.reinitializeCharts();
}
// ------------------------------------------------------------------------
*/
@Override
public Control getControl() {
- return fTreeViewer.getControl();
+ return fSash;
}
/**
return fStatisticsData;
}
+ /**
+ * @return the model of the piecharts in this viewer
+ * @since 2.0
+ */
+ public TmfPieChartStatisticsModel getPieChartModel(){
+ if (fPieChartModel == null) {
+ fPieChartModel = new TmfPieChartStatisticsModel();
+ }
+ return fPieChartModel;
+ }
+
/**
* Returns a unique ID based on name to be associated with the statistics
* tree for this viewer. For a same name, it will always return the same ID.
if (viewerControl.isDisposed()) {
return;
}
+ refreshTree();
+ refreshPieCharts(true, true);
+ }
+
+ /**
+ * Only refreshes the Tree viewer
+ */
+ private void refreshTree(){
+ final Control viewerControl = getControl();
+ // Ignore update if disposed
+ if (viewerControl.isDisposed()) {
+ return;
+ }
- TmfUiRefreshHandler.getInstance().queueUpdate(this, new Runnable() {
+ Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!viewerControl.isDisposed()) {
});
}
+ /**
+ * Only refreshes the piecharts depending on the parameters
+ * @param refreshGlobal if we have to refresh the global piechart
+ * @param refreshSelection if we have to refresh the selection piechart
+ * @since 2.0
+ */
+ protected void refreshPieCharts(final boolean refreshGlobal, final boolean refreshSelection) {
+ final Control viewerControl = getControl();
+ // Ignore update if disposed
+ if (viewerControl.isDisposed()) {
+ return;
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!viewerControl.isDisposed()) {
+ fPieChartViewer.refresh(refreshGlobal, refreshSelection);
+ }
+ }
+ });
+ }
+
/**
* Will force a request on the partial event count if one is needed.
*/
* The parent of the control to create
*/
protected void initContent(Composite parent) {
+
final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
- fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ fSash = new SashForm(parent, SWT.HORIZONTAL );
+
+ fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ fPieChartViewer = new TmfPieChartViewer(fSash);
+ fSash.setWeights(new int[]{100,100});
+
fTreeViewer.setContentProvider(new TmfTreeContentProvider());
fTreeViewer.getTree().setHeaderVisible(true);
fTreeViewer.setUseHashlookup(true);
// Sets the input to a clean data model
fTreeViewer.setInput(statisticsTreeNode);
+ /* Set a new model for the piecharts and keep a reference */
+ fPieChartViewer.setInput(getPieChartModel());
}
/**
* request.
*/
protected void modelComplete(boolean global) {
- refresh();
- waitCursor(false);
- }
-
- /**
- * Called when an trace request has failed or has been cancelled.
- *
- * @param isGlobalRequest
- * Tells if the request is a global or time range (partial)
- * request.
- */
- protected void modelIncomplete(boolean isGlobalRequest) {
- if (isGlobalRequest) { // Clean the global statistics
- /*
- * No need to reset the global number of events, since the index of
- * the last requested event is known.
- */
- } else { // Clean the partial statistics
- resetTimeRangeValue();
- }
- refresh();
+ refreshTree();
waitCursor(false);
}
Map<ITmfTrace, Job> updateJobs;
if (isGlobal) {
updateJobs = fUpdateJobsGlobal;
- fTimeRange = timeRange;
} else {
updateJobs = fUpdateJobsPartial;
- fTimeRangePartial = timeRange;
}
for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
Job job = updateJobs.get(aTrace);
if (job == null) {
- job = new UpdateJob("Statistics update", aTrace, isGlobal, statsMod); //$NON-NLS-1$
+ job = new StatisticsUpdateJob("Statistics update", aTrace, isGlobal, timeRange, statsMod, this); //$NON-NLS-1$
updateJobs.put(aTrace, job);
job.setSystem(true);
job.schedule();
}
}
- private class UpdateJob extends Job {
-
- private final ITmfTrace fJobTrace;
- private final boolean fIsGlobal;
- private final TmfStatisticsModule fStatsMod;
-
- private UpdateJob(String name, ITmfTrace trace, boolean isGlobal, TmfStatisticsModule statsMod) {
- super(name);
- fJobTrace = trace;
- fIsGlobal = isGlobal;
- fStatsMod = statsMod;
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
-
- /* Wait until the analysis is ready to be queried */
- fStatsMod.waitForInitialization();
- ITmfStatistics stats = fStatsMod.getStatistics();
- if (stats == null) {
- /* It should have worked, but didn't */
- throw new IllegalStateException();
- }
-
- /*
- * TODO Eventually this could be exposed through the
- * TmfStateSystemAnalysisModule directly.
- */
- ITmfStateSystem ss = fStatsMod.getStateSystem(TmfStatisticsEventTypesModule.ID);
- if (ss == null) {
- /* It should be instantiated after the
- * statsMod.waitForInitialization() above. */
- throw new IllegalStateException();
- }
-
-
- /*
- * Periodically update the statistics while they are
- * being built (or, if the back-end is already completely
- * built, it will skip over the while() immediately.
- */
- long start = 0;
- long end = 0;
- boolean finished = false;
- do {
- if (monitor.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
- finished = ss.waitUntilBuilt(LIVE_UPDATE_DELAY);
-
- TmfTimeRange localtimeRange = fIsGlobal ? fTimeRange : fTimeRangePartial;
- /*
- * The generic statistics are stored in nanoseconds, so
- * we must make sure the time range is scaled correctly.
- */
- start = localtimeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
- end = localtimeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
-
- Map<String, Long> map = stats.getEventTypesInRange(start, end);
- updateStats(map);
- } while (!finished);
-
- /* Query one last time for the final values */
- Map<String, Long> map = stats.getEventTypesInRange(start, end);
- updateStats(map);
-
- /*
- * Remove job from map so that new range selection updates can
- * be processed.
- */
- Map<ITmfTrace, Job> updateJobs;
- if (fIsGlobal) {
- updateJobs = fUpdateJobsGlobal;
- } else {
- updateJobs = fUpdateJobsPartial;
- }
- updateJobs.remove(fJobTrace);
- return Status.OK_STATUS;
- }
-
- /*
- * Update statistics for a given trace
- */
- private void updateStats(Map<String, Long> eventsPerType) {
-
- final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
- if (statsData == null) {
- /* The stat tree has been disposed, abort mission. */
- return;
- }
-
- Map<String, Long> map = eventsPerType;
- String name = fJobTrace.getName();
-
-
- /*
- * "Global", "partial", "total", etc., it's all very confusing...
- *
- * The base view shows the total count for the trace and for
- * each even types, organized in columns like this:
- *
- * | Global | Time range |
- * trace name | A | B |
- * Event Type | | |
- * <event 1> | C | D |
- * <event 2> | ... | ... |
- * ... | | |
- *
- * Here, we called the cells like this:
- * A : GlobalTotal
- * B : TimeRangeTotal
- * C : GlobalTypeCount(s)
- * D : TimeRangeTypeCount(s)
- */
-
- /* Fill in an the event counts (either cells C or D) */
- for (Map.Entry<String, Long> entry : map.entrySet()) {
- statsData.setTypeCount(name, entry.getKey(), fIsGlobal, entry.getValue());
- }
-
- /*
- * Calculate the totals (cell A or B, depending if isGlobal). We will
- * use the results of the previous request instead of sending another
- * one.
- */
- long globalTotal = 0;
- for (long val : map.values()) {
- globalTotal += val;
- }
- statsData.setTotal(name, fIsGlobal, globalTotal);
-
- modelComplete(fIsGlobal);
- }
- }
-
/**
* Resets the number of events within the time range
*/
});
}
}
+
+ /**
+ * @param isGlobal if the job to remove is global or partial
+ * @param jobTrace The trace
+ */
+ void removeFromJobs(boolean isGlobal, ITmfTrace jobTrace) {
+ Map<ITmfTrace, Job> updateJobs = isGlobal ? fUpdateJobsGlobal : fUpdateJobsPartial;
+ Job job = updateJobs.remove(jobTrace);
+ if (job != null) {
+ job.cancel();
+ }
+ }
}
# Ericsson - Initial API and implementation
###############################################################################
-TmfStatisticsView_UnknownTraceName=Unknown_Trace
\ No newline at end of file
+TmfStatisticsView_UnknownTraceName=Unknown_Trace