tmf: make CallstackProvider entry and exit return TmfStates
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractStateSystemTimeGraphView.java
CommitLineData
6ae6c5bd 1/*******************************************************************************
f8f46a52 2 * Copyright (c) 2015, 2016 Ericsson
6ae6c5bd
PT
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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.tracecompass.tmf.ui.views.timegraph;
14
15import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21import java.util.concurrent.CopyOnWriteArrayList;
22
23import org.eclipse.core.runtime.IProgressMonitor;
24import org.eclipse.jdt.annotation.NonNull;
25import org.eclipse.jdt.annotation.Nullable;
26import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
27import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
28import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
6ae6c5bd
PT
29import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
30import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
31import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
e790b877 32import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
6ae6c5bd 33import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
6ae6c5bd
PT
34import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
35
36import com.google.common.collect.HashMultimap;
37import com.google.common.collect.Multimap;
38
39/**
40 * An abstract time graph view where each entry's time event list is populated
41 * from a state system. The state system full state is queried in chronological
42 * order before creating the time event lists as this is optimal for state
43 * system queries.
44 *
0336f981 45 * @since 1.1
6ae6c5bd
PT
46 */
47public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraphView {
48
49 // ------------------------------------------------------------------------
50 // Constants
51 // ------------------------------------------------------------------------
52
53 private static final long MAX_INTERVALS = 1000000;
54
55 // ------------------------------------------------------------------------
56 // Fields
57 // ------------------------------------------------------------------------
58
59 /** The state system to entry list hash map */
60 private final Map<ITmfStateSystem, List<TimeGraphEntry>> fSSEntryListMap = new HashMap<>();
61
62 /** The trace to state system multi map */
63 private final Multimap<ITmfTrace, ITmfStateSystem> fTraceSSMap = HashMultimap.create();
64
65 // ------------------------------------------------------------------------
66 // Classes
67 // ------------------------------------------------------------------------
68
69 /**
70 * Handler for state system queries
71 */
72 public interface IQueryHandler {
73 /**
74 * Handle a full or partial list of full states. This can be called many
75 * times for the same query if the query result is split, in which case
76 * the previous full state is null only the first time it is called, and
77 * set to the last full state of the previous call from then on.
78 *
79 * @param fullStates
80 * the list of full states
81 * @param prevFullState
82 * the previous full state, or null
83 */
84 void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState);
85 }
86
87 private class ZoomThreadByTime extends ZoomThread {
88 private final @NonNull List<ITmfStateSystem> fZoomSSList;
89 private boolean fClearZoomedLists;
90
91 public ZoomThreadByTime(@NonNull List<ITmfStateSystem> ssList, long startTime, long endTime, long resolution, boolean restart) {
92 super(startTime, endTime, resolution);
93 fZoomSSList = ssList;
94 fClearZoomedLists = !restart;
95 }
96
97 @Override
156e9ead 98 public void doRun() {
6ae6c5bd 99 final List<ILinkEvent> links = new ArrayList<>();
e790b877 100 final List<IMarkerEvent> markers = new ArrayList<>();
6ae6c5bd
PT
101 if (fClearZoomedLists) {
102 clearZoomedLists();
103 }
104 for (ITmfStateSystem ss : fZoomSSList) {
105 List<TimeGraphEntry> entryList = null;
106 synchronized (fSSEntryListMap) {
107 entryList = fSSEntryListMap.get(ss);
108 }
109 if (entryList != null) {
e790b877 110 zoomByTime(ss, entryList, links, markers, getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
6ae6c5bd
PT
111 }
112 }
113 if (!getMonitor().isCanceled()) {
24333461
PT
114 /* Refresh the trace-specific markers when zooming */
115 markers.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
6d28f3e8
MAL
116 applyResults(() -> {
117 getTimeGraphViewer().setLinks(links);
118 getTimeGraphViewer().setMarkers(markers);
119 });
6ae6c5bd
PT
120 }
121 }
122
123 @Override
124 public void cancel() {
125 super.cancel();
126 if (fClearZoomedLists) {
127 clearZoomedLists();
128 }
129 }
130
e790b877 131 private void zoomByTime(final ITmfStateSystem ss, final List<TimeGraphEntry> entryList, final List<ILinkEvent> links, final List<IMarkerEvent> markers,
6ae6c5bd
PT
132 long startTime, long endTime, long resolution, final @NonNull IProgressMonitor monitor) {
133 final long start = Math.max(startTime, ss.getStartTime());
134 final long end = Math.min(endTime, ss.getCurrentEndTime());
135 final boolean fullRange = getZoomStartTime() <= getStartTime() && getZoomEndTime() >= getEndTime();
136 if (end < start) {
137 return;
138 }
139 if (fullRange) {
140 redraw();
141 }
142 queryFullStates(ss, start, end, resolution, monitor, new IQueryHandler() {
143 @Override
144 public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
145 if (!fullRange) {
146 for (TimeGraphEntry entry : entryList) {
147 zoom(checkNotNull(entry), ss, fullStates, prevFullState, monitor);
148 }
149 }
150 /* Refresh the arrows when zooming */
143217ee 151 links.addAll(getLinkList(ss, fullStates, prevFullState, monitor));
24333461
PT
152 /* Refresh the view-specific markers when zooming */
153 markers.addAll(getViewMarkerList(ss, fullStates, prevFullState, monitor));
6ae6c5bd
PT
154 }
155 });
156 refresh();
157 }
158
159 private void zoom(@NonNull TimeGraphEntry entry, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
160 List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
161 if (eventList != null) {
6d28f3e8
MAL
162 applyResults(() -> {
163 for (ITimeEvent event : eventList) {
164 if (monitor.isCanceled()) {
165 return;
166 }
167 entry.addZoomedEvent(event);
168 }
169 });
6ae6c5bd 170 }
f8f46a52 171 for (TimeGraphEntry child : entry.getChildren()) {
6ae6c5bd
PT
172 if (monitor.isCanceled()) {
173 return;
174 }
f8f46a52 175 zoom(child, ss, fullStates, prevFullState, monitor);
6ae6c5bd
PT
176 }
177 }
178
179 private void clearZoomedLists() {
180 for (ITmfStateSystem ss : fZoomSSList) {
181 List<TimeGraphEntry> entryList = null;
182 synchronized (fSSEntryListMap) {
183 entryList = fSSEntryListMap.get(ss);
184 }
185 if (entryList != null) {
186 for (TimeGraphEntry entry : entryList) {
187 clearZoomedList(entry);
188 }
189 }
190 }
191 fClearZoomedLists = false;
192 }
193
194 private void clearZoomedList(TimeGraphEntry entry) {
195 entry.setZoomedEventList(null);
f8f46a52
PT
196 for (TimeGraphEntry child : entry.getChildren()) {
197 clearZoomedList(child);
6ae6c5bd
PT
198 }
199 }
200 }
201
202 // ------------------------------------------------------------------------
203 // Constructors
204 // ------------------------------------------------------------------------
205
206 /**
207 * Constructs a time graph view that contains either a time graph viewer or
208 * a time graph combo.
209 *
210 * By default, the view uses a time graph viewer. To use a time graph combo,
211 * the subclass constructor must call {@link #setTreeColumns(String[])} and
212 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
213 *
214 * @param id
215 * The id of the view
216 * @param pres
217 * The presentation provider
218 */
219 public AbstractStateSystemTimeGraphView(String id, TimeGraphPresentationProvider pres) {
220 super(id, pres);
221 }
222
223 // ------------------------------------------------------------------------
224 // Internal
225 // ------------------------------------------------------------------------
226
227 /**
228 * Gets the entry list for a state system
229 *
230 * @param ss
231 * the state system
232 *
233 * @return the entry list map
234 */
235 protected List<TimeGraphEntry> getEntryList(ITmfStateSystem ss) {
236 synchronized (fSSEntryListMap) {
237 return fSSEntryListMap.get(ss);
238 }
239 }
240
241 /**
242 * Adds a trace entry list to the entry list map
243 *
244 * @param trace
245 * the trace
246 * @param ss
247 * the state system
248 * @param list
249 * the list of time graph entries
250 */
251 protected void putEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
252 super.putEntryList(trace, list);
253 synchronized (fSSEntryListMap) {
254 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
255 fTraceSSMap.put(trace, ss);
256 }
257 }
258
259 /**
260 * Adds a list of entries to a trace's entry list
261 *
262 * @param trace
263 * the trace
264 * @param ss
265 * the state system
266 * @param list
267 * the list of time graph entries to add
268 */
269 protected void addToEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
270 super.addToEntryList(trace, list);
271 synchronized (fSSEntryListMap) {
272 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
273 if (entryList == null) {
274 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
275 } else {
276 entryList.addAll(list);
277 }
278 fTraceSSMap.put(trace, ss);
279 }
280 }
281
282 /**
283 * Removes a list of entries from a trace's entry list
284 *
285 * @param trace
286 * the trace
287 * @param ss
288 * the state system
289 * @param list
290 * the list of time graph entries to remove
291 */
292 protected void removeFromEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
293 super.removeFromEntryList(trace, list);
294 synchronized (fSSEntryListMap) {
295 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
296 if (entryList != null) {
297 entryList.removeAll(list);
298 if (entryList.isEmpty()) {
299 fTraceSSMap.remove(trace, ss);
300 }
301 }
302 }
303 }
304
305 @Override
306 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
307 List<ITmfStateSystem> ssList = null;
308 synchronized (fSSEntryListMap) {
309 ssList = new ArrayList<>(fTraceSSMap.get(getTrace()));
310 }
311 if (ssList.isEmpty()) {
312 return null;
313 }
314 return new ZoomThreadByTime(ssList, startTime, endTime, resolution, restart);
315 }
316
317 /**
318 * Query the state system full state for the given time range.
319 *
320 * @param ss
321 * The state system
322 * @param start
323 * The start time
324 * @param end
325 * The end time
326 * @param resolution
327 * The resolution
328 * @param monitor
329 * The progress monitor
330 * @param handler
331 * The query handler
332 */
333 protected void queryFullStates(ITmfStateSystem ss, long start, long end, long resolution,
334 @NonNull IProgressMonitor monitor, @NonNull IQueryHandler handler) {
335 List<List<ITmfStateInterval>> fullStates = new ArrayList<>();
336 List<ITmfStateInterval> prevFullState = null;
337 try {
338 long time = start;
339 while (true) {
340 if (monitor.isCanceled()) {
341 break;
342 }
343 List<ITmfStateInterval> fullState = ss.queryFullState(time);
344 fullStates.add(fullState);
345 if (fullStates.size() * fullState.size() > MAX_INTERVALS) {
346 handler.handle(fullStates, prevFullState);
347 prevFullState = fullStates.get(fullStates.size() - 1);
348 fullStates.clear();
349 }
350 if (time >= end) {
351 break;
352 }
353 time = Math.min(end, time + resolution);
354 }
355 if (fullStates.size() > 0) {
356 handler.handle(fullStates, prevFullState);
357 }
358 } catch (StateSystemDisposedException e) {
359 /* Ignored */
360 }
361 }
362
363 /**
364 * Gets the list of events for an entry for a given list of full states.
f8f46a52
PT
365 * <p>
366 * Called from the ZoomThread for every entry to update the zoomed event
367 * list. Can be an empty implementation if the view does not support zoomed
368 * event lists. Can also be used to compute the full event list.
6ae6c5bd
PT
369 *
370 * @param tgentry
371 * The time graph entry
372 * @param ss
373 * The state system
374 * @param fullStates
375 * A list of full states
376 * @param prevFullState
377 * The previous full state, or null
378 * @param monitor
379 * A progress monitor
380 * @return The list of time graph events
6ae6c5bd
PT
381 */
382 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
383 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor);
384
385 /**
386 * Gets the list of links (displayed as arrows) for a given list of full
387 * states. The default implementation returns an empty list.
388 *
389 * @param ss
390 * The state system
391 * @param fullStates
392 * A list of full states
143217ee
PT
393 * @param prevFullState
394 * The previous full state, or null
6ae6c5bd
PT
395 * @param monitor
396 * A progress monitor
397 * @return The list of link events
143217ee 398 * @since 2.0
6ae6c5bd
PT
399 */
400 protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
143217ee 401 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
6ae6c5bd
PT
402 return new ArrayList<>();
403 }
404
e790b877
PT
405 /**
406 * Gets the list of markers for a given list of full
407 * states. The default implementation returns an empty list.
408 *
409 * @param ss
410 * The state system
411 * @param fullStates
412 * A list of full states
143217ee
PT
413 * @param prevFullState
414 * The previous full state, or null
e790b877
PT
415 * @param monitor
416 * A progress monitor
417 * @return The list of marker events
5dd0ebfe 418 * @since 2.0
e790b877 419 */
24333461 420 protected @NonNull List<IMarkerEvent> getViewMarkerList(ITmfStateSystem ss,
143217ee 421 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
e790b877
PT
422 return new ArrayList<>();
423 }
424
6ae6c5bd
PT
425 /**
426 * @deprecated The subclass should call {@link #getEntryList(ITmfStateSystem)} instead.
427 */
428 @Deprecated
429 @Override
430 protected final List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
431 throw new UnsupportedOperationException();
432 }
433
434 /**
435 * @deprecated The subclass should call {@link #addToEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
436 */
437 @Deprecated
438 @Override
439 protected final void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
440 throw new UnsupportedOperationException();
441 }
442
443 /**
444 * @deprecated The subclass should call {@link #putEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
445 */
446 @Deprecated
447 @Override
448 protected final void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
449 throw new UnsupportedOperationException();
450 }
451
452 /**
453 * @deprecated The subclass should call {@link #removeFromEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
454 */
455 @Deprecated
456 @Override
457 protected final void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
458 throw new UnsupportedOperationException();
459 }
460
461 /**
462 * @deprecated The subclass should implement {@link #getEventList(TimeGraphEntry, ITmfStateSystem, List, List, IProgressMonitor)} instead.
463 */
464 @Deprecated
465 @Override
466 protected final List<ITimeEvent> getEventList(TimeGraphEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
467 throw new UnsupportedOperationException();
468 }
469
470 /**
143217ee 471 * @deprecated The subclass should implement {@link #getLinkList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
6ae6c5bd
PT
472 */
473 @Deprecated
474 @Override
475 protected final List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
476 throw new UnsupportedOperationException();
477 }
478
e790b877 479 /**
24333461 480 * @deprecated The subclass should implement {@link #getViewMarkerList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
e790b877
PT
481 */
482 @Deprecated
483 @Override
24333461 484 protected final List<IMarkerEvent> getViewMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
e790b877
PT
485 throw new UnsupportedOperationException();
486 }
487
6ae6c5bd 488 @Override
dbae6118
BH
489 protected void resetView(ITmfTrace viewTrace) {
490 // Don't remove super call
491 super.resetView(viewTrace);
6ae6c5bd 492 synchronized (fSSEntryListMap) {
dbae6118 493 for (ITmfStateSystem ss : fTraceSSMap.removeAll(viewTrace)) {
6ae6c5bd
PT
494 fSSEntryListMap.remove(ss);
495 }
496 }
497 }
498}
This page took 0.063234 seconds and 5 git commands to generate.