tmf: Bug 494767: Events in selection not updated in Statistics view
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / viewers / statistics / StatisticsUpdateJob.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Mathieu Denis - Initial API and implementation
11 * Alexis Cabana-Loriaux - Extract the class in a compilation unit
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics;
15
16 import java.util.Map;
17
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.core.runtime.jobs.Job;
22 import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
23 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
24 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
25 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
26 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
27 import org.eclipse.tracecompass.tmf.core.statistics.ITmfStatistics;
28 import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
29 import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
30 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
31 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
32
33 /**
34 * Class used to update the Statistics view. Normally, it should only be used by
35 * this class
36 *
37 * @author Mathieu Denis
38 */
39 class StatisticsUpdateJob extends Job {
40
41 private final ITmfTrace fJobTrace;
42 private final boolean fIsGlobal;
43 private final TmfStatisticsModule fStatsMod;
44 private final TmfStatisticsViewer fViewer;
45
46 /**
47 * The delay (in ms) between each update in live-reading mode
48 */
49 private static final long LIVE_UPDATE_DELAY = 1000;
50
51 private TmfTimeRange fTimerange;
52
53 /**
54 * @param name
55 * The name of the working job
56 * @param trace
57 * The trace to query
58 * @param isGlobal
59 * If the query is for the global time-range or a selection
60 * time-range
61 * @param timerange
62 * The timerange of
63 * @param statsMod
64 * The statistics module of the trace
65 * @param viewer
66 * The viewer to update
67 */
68 public StatisticsUpdateJob(String name, ITmfTrace trace, boolean isGlobal, TmfTimeRange timerange, TmfStatisticsModule statsMod, TmfStatisticsViewer viewer) {
69 super(name);
70 fJobTrace = trace;
71 fIsGlobal = isGlobal;
72 fTimerange = timerange;
73 fStatsMod = statsMod;
74 fViewer = viewer;
75 }
76
77 @Override
78 protected IStatus run(IProgressMonitor monitor) {
79
80 /* Wait until the analysis is ready to be queried */
81 if (!fStatsMod.waitForInitialization()) {
82 return Status.CANCEL_STATUS;
83 }
84 ITmfStatistics stats = fStatsMod.getStatistics();
85 if (stats == null) {
86 /* It should have worked, but didn't */
87 throw new IllegalStateException();
88 }
89
90 /*
91 * TODO Eventually this could be exposed through the
92 * TmfStateSystemAnalysisModule directly.
93 */
94 ITmfStateSystem ss = fStatsMod.getStateSystem(TmfStatisticsEventTypesModule.ID);
95 if (ss == null) {
96 /*
97 * It should be instantiated after the
98 * statsMod.waitForInitialization() above.
99 */
100 throw new IllegalStateException();
101 }
102
103 /*
104 * Periodically update the statistics while they are being built (or, if
105 * the back-end is already completely built, it will skip over the
106 * while() immediately.
107 */
108 long start = 0;
109 long end = 0;
110 boolean finished = false;
111 do {
112 /* This model update is done every second */
113 if (monitor.isCanceled()) {
114 fViewer.removeFromJobs(fIsGlobal, fJobTrace);
115 return Status.CANCEL_STATUS;
116 }
117 finished = ss.waitUntilBuilt(LIVE_UPDATE_DELAY);
118 TmfTimeRange localtimeRange = fTimerange;
119 /*
120 * The generic statistics are stored in nanoseconds, so we must make
121 * sure the time range is scaled correctly.
122 */
123 start = localtimeRange.getStartTime().toNanos();
124 end = localtimeRange.getEndTime().toNanos();
125
126 Map<String, Long> map = stats.getEventTypesInRange(start, end);
127 updateStats(map);
128 } while (!finished);
129
130
131 /* Query one last time for the final values */
132 Map<String, Long> map = stats.getEventTypesInRange(start, end);
133 updateStats(map);
134 fViewer.refreshPieCharts(fIsGlobal, !fIsGlobal);
135 /*
136 * Remove job from map so that new range selection updates can be
137 * processed.
138 */
139 fViewer.removeFromJobs(fIsGlobal, fJobTrace);
140 return Status.OK_STATUS;
141 }
142
143 /*
144 * Update the tree for a given trace
145 */
146 private void updateStats(Map<String, Long> eventsPerType) {
147
148 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(fViewer.getTreeID());
149 if (statsData == null) {
150 /* The stat tree has been disposed, abort mission. */
151 return;
152 }
153
154 Map<String, Long> map = eventsPerType;
155 String name = fJobTrace.getName();
156
157 /**
158 * <pre>
159 * "Global", "partial", "total", etc., it's all very confusing...
160 *
161 * The base view shows the total count for the trace and for
162 * each even types, organized in columns like this:
163 *
164 * | Global | Time range |
165 * trace name | A | B |
166 * Event Type | | |
167 * <event 1> | C | D |
168 * <event 2> | ... | ... |
169 * ... | | |
170 *
171 * Here, we called the cells like this:
172 * A : GlobalTotal
173 * B : TimeRangeTotal
174 * C : GlobalTypeCount(s)
175 * D : TimeRangeTypeCount(s)
176 * </pre>
177 */
178
179 if (map.isEmpty() && !fIsGlobal) {
180 /* Reset all time range event counts (cells D) */
181 TmfStatisticsTreeNode eventTypeNode = statsData.getNode(name, TmfStatisticsTree.HEADER_EVENT_TYPES);
182 if (eventTypeNode != null) {
183 eventTypeNode.resetTimeRangeValue();
184 }
185 } else {
186 /* Fill in the event counts (either cells C or D) */
187 for (Map.Entry<String, Long> entry : map.entrySet()) {
188 statsData.setTypeCount(name, entry.getKey(), fIsGlobal, entry.getValue());
189 }
190 }
191
192 /*
193 * Calculate the totals (cell A or B, depending if isGlobal). We will
194 * use the results of the previous request instead of sending another
195 * one.
196 */
197 long globalTotal = 0;
198 for (long val : map.values()) {
199 globalTotal += val;
200 }
201 /* Update both the tree model and the piechart model */
202 statsData.setTotal(name, fIsGlobal, globalTotal);
203 TmfPieChartStatisticsModel model = fViewer.getPieChartModel();
204 if (model != null) {
205 model.setPieChartTypeCount(fIsGlobal, fJobTrace, eventsPerType);
206 }
207 /* notify that the viewer needs to be refreshed */
208 fViewer.modelComplete(fIsGlobal);
209 }
210 }
This page took 0.045041 seconds and 5 git commands to generate.