blob: 8823f7f94cf36a2b76dc967da4e017c8dd0db51e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Mathieu Denis - Initial API and implementation
* Alexis Cabana-Loriaux - Extract the class in a compilation unit
*******************************************************************************/
package org.eclipse.tracecompass.internal.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.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
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.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
* 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;
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) {
IStatus st = fStatsMod.schedule();
if (!st.isOK()) {
return st;
}
/* Wait until the analysis is ready to be queried */
if (!fStatsMod.waitForInitialization()) {
return Status.CANCEL_STATUS;
}
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().toNanos();
end = localtimeRange.getEndTime().toNanos();
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>
*/
if (map.isEmpty() && !fIsGlobal) {
/* Reset all time range event counts (cells D) */
TmfStatisticsTreeNode eventTypeNode = statsData.getNode(name, TmfStatisticsTree.HEADER_EVENT_TYPES);
if (eventTypeNode != null) {
eventTypeNode.resetTimeRangeValue();
}
} else {
/* Fill in 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);
}
}