lttng: Make ControlFlowViewTest more robust
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractStateSystemTimeGraphView.java
CommitLineData
6ae6c5bd
PT
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 * 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;
29import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
30import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
31import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
32import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
33import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
e790b877 34import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
6ae6c5bd
PT
35import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
36import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
37import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
38
39import com.google.common.collect.HashMultimap;
40import com.google.common.collect.Multimap;
41
42/**
43 * An abstract time graph view where each entry's time event list is populated
44 * from a state system. The state system full state is queried in chronological
45 * order before creating the time event lists as this is optimal for state
46 * system queries.
47 *
0336f981 48 * @since 1.1
6ae6c5bd
PT
49 */
50public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraphView {
51
52 // ------------------------------------------------------------------------
53 // Constants
54 // ------------------------------------------------------------------------
55
56 private static final long MAX_INTERVALS = 1000000;
57
58 // ------------------------------------------------------------------------
59 // Fields
60 // ------------------------------------------------------------------------
61
62 /** The state system to entry list hash map */
63 private final Map<ITmfStateSystem, List<TimeGraphEntry>> fSSEntryListMap = new HashMap<>();
64
65 /** The trace to state system multi map */
66 private final Multimap<ITmfTrace, ITmfStateSystem> fTraceSSMap = HashMultimap.create();
67
68 // ------------------------------------------------------------------------
69 // Classes
70 // ------------------------------------------------------------------------
71
72 /**
73 * Handler for state system queries
74 */
75 public interface IQueryHandler {
76 /**
77 * Handle a full or partial list of full states. This can be called many
78 * times for the same query if the query result is split, in which case
79 * the previous full state is null only the first time it is called, and
80 * set to the last full state of the previous call from then on.
81 *
82 * @param fullStates
83 * the list of full states
84 * @param prevFullState
85 * the previous full state, or null
86 */
87 void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState);
88 }
89
90 private class ZoomThreadByTime extends ZoomThread {
91 private final @NonNull List<ITmfStateSystem> fZoomSSList;
92 private boolean fClearZoomedLists;
93
94 public ZoomThreadByTime(@NonNull List<ITmfStateSystem> ssList, long startTime, long endTime, long resolution, boolean restart) {
95 super(startTime, endTime, resolution);
96 fZoomSSList = ssList;
97 fClearZoomedLists = !restart;
98 }
99
100 @Override
156e9ead 101 public void doRun() {
6ae6c5bd 102 final List<ILinkEvent> links = new ArrayList<>();
e790b877 103 final List<IMarkerEvent> markers = new ArrayList<>();
6ae6c5bd
PT
104 if (fClearZoomedLists) {
105 clearZoomedLists();
106 }
107 for (ITmfStateSystem ss : fZoomSSList) {
108 List<TimeGraphEntry> entryList = null;
109 synchronized (fSSEntryListMap) {
110 entryList = fSSEntryListMap.get(ss);
111 }
112 if (entryList != null) {
e790b877 113 zoomByTime(ss, entryList, links, markers, getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
6ae6c5bd
PT
114 }
115 }
116 if (!getMonitor().isCanceled()) {
117 getTimeGraphViewer().setLinks(links);
24333461
PT
118 /* Refresh the trace-specific markers when zooming */
119 markers.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
f72cd563 120 getTimeGraphViewer().setMarkers(markers);
6ae6c5bd
PT
121 }
122 }
123
124 @Override
125 public void cancel() {
126 super.cancel();
127 if (fClearZoomedLists) {
128 clearZoomedLists();
129 }
130 }
131
e790b877 132 private void zoomByTime(final ITmfStateSystem ss, final List<TimeGraphEntry> entryList, final List<ILinkEvent> links, final List<IMarkerEvent> markers,
6ae6c5bd
PT
133 long startTime, long endTime, long resolution, final @NonNull IProgressMonitor monitor) {
134 final long start = Math.max(startTime, ss.getStartTime());
135 final long end = Math.min(endTime, ss.getCurrentEndTime());
136 final boolean fullRange = getZoomStartTime() <= getStartTime() && getZoomEndTime() >= getEndTime();
137 if (end < start) {
138 return;
139 }
140 if (fullRange) {
141 redraw();
142 }
143 queryFullStates(ss, start, end, resolution, monitor, new IQueryHandler() {
144 @Override
145 public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
146 if (!fullRange) {
147 for (TimeGraphEntry entry : entryList) {
148 zoom(checkNotNull(entry), ss, fullStates, prevFullState, monitor);
149 }
150 }
151 /* Refresh the arrows when zooming */
143217ee 152 links.addAll(getLinkList(ss, fullStates, prevFullState, monitor));
24333461
PT
153 /* Refresh the view-specific markers when zooming */
154 markers.addAll(getViewMarkerList(ss, fullStates, prevFullState, monitor));
6ae6c5bd
PT
155 }
156 });
157 refresh();
158 }
159
160 private void zoom(@NonNull TimeGraphEntry entry, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
161 List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
162 if (eventList != null) {
163 for (ITimeEvent event : eventList) {
164 entry.addZoomedEvent(event);
165 }
166 }
167 for (ITimeGraphEntry child : entry.getChildren()) {
168 if (monitor.isCanceled()) {
169 return;
170 }
171 if (child instanceof TimeGraphEntry) {
172 zoom((TimeGraphEntry) child, ss, fullStates, prevFullState, monitor);
173 }
174 }
175 }
176
177 private void clearZoomedLists() {
178 for (ITmfStateSystem ss : fZoomSSList) {
179 List<TimeGraphEntry> entryList = null;
180 synchronized (fSSEntryListMap) {
181 entryList = fSSEntryListMap.get(ss);
182 }
183 if (entryList != null) {
184 for (TimeGraphEntry entry : entryList) {
185 clearZoomedList(entry);
186 }
187 }
188 }
189 fClearZoomedLists = false;
190 }
191
192 private void clearZoomedList(TimeGraphEntry entry) {
193 entry.setZoomedEventList(null);
194 for (ITimeGraphEntry child : entry.getChildren()) {
195 if (child instanceof TimeGraphEntry) {
196 clearZoomedList((TimeGraphEntry) child);
197 }
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.
365 *
366 * @param tgentry
367 * The time graph entry
368 * @param ss
369 * The state system
370 * @param fullStates
371 * A list of full states
372 * @param prevFullState
373 * The previous full state, or null
374 * @param monitor
375 * A progress monitor
376 * @return The list of time graph events
6ae6c5bd
PT
377 */
378 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
379 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor);
380
381 /**
382 * Gets the list of links (displayed as arrows) for a given list of full
383 * states. The default implementation returns an empty list.
384 *
385 * @param ss
386 * The state system
387 * @param fullStates
388 * A list of full states
143217ee
PT
389 * @param prevFullState
390 * The previous full state, or null
6ae6c5bd
PT
391 * @param monitor
392 * A progress monitor
393 * @return The list of link events
143217ee 394 * @since 2.0
6ae6c5bd
PT
395 */
396 protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
143217ee 397 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
6ae6c5bd
PT
398 return new ArrayList<>();
399 }
400
e790b877
PT
401 /**
402 * Gets the list of markers for a given list of full
403 * states. The default implementation returns an empty list.
404 *
405 * @param ss
406 * The state system
407 * @param fullStates
408 * A list of full states
143217ee
PT
409 * @param prevFullState
410 * The previous full state, or null
e790b877
PT
411 * @param monitor
412 * A progress monitor
413 * @return The list of marker events
5dd0ebfe 414 * @since 2.0
e790b877 415 */
24333461 416 protected @NonNull List<IMarkerEvent> getViewMarkerList(ITmfStateSystem ss,
143217ee 417 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
e790b877
PT
418 return new ArrayList<>();
419 }
420
6ae6c5bd
PT
421 /**
422 * @deprecated The subclass should call {@link #getEntryList(ITmfStateSystem)} instead.
423 */
424 @Deprecated
425 @Override
426 protected final List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
427 throw new UnsupportedOperationException();
428 }
429
430 /**
431 * @deprecated The subclass should call {@link #addToEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
432 */
433 @Deprecated
434 @Override
435 protected final void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
436 throw new UnsupportedOperationException();
437 }
438
439 /**
440 * @deprecated The subclass should call {@link #putEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
441 */
442 @Deprecated
443 @Override
444 protected final void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
445 throw new UnsupportedOperationException();
446 }
447
448 /**
449 * @deprecated The subclass should call {@link #removeFromEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
450 */
451 @Deprecated
452 @Override
453 protected final void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
454 throw new UnsupportedOperationException();
455 }
456
457 /**
458 * @deprecated The subclass should implement {@link #getEventList(TimeGraphEntry, ITmfStateSystem, List, List, IProgressMonitor)} instead.
459 */
460 @Deprecated
461 @Override
462 protected final List<ITimeEvent> getEventList(TimeGraphEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
463 throw new UnsupportedOperationException();
464 }
465
466 /**
143217ee 467 * @deprecated The subclass should implement {@link #getLinkList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
6ae6c5bd
PT
468 */
469 @Deprecated
470 @Override
471 protected final List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
472 throw new UnsupportedOperationException();
473 }
474
e790b877 475 /**
24333461 476 * @deprecated The subclass should implement {@link #getViewMarkerList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
e790b877
PT
477 */
478 @Deprecated
479 @Override
24333461 480 protected final List<IMarkerEvent> getViewMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
e790b877
PT
481 throw new UnsupportedOperationException();
482 }
483
6ae6c5bd
PT
484 // ------------------------------------------------------------------------
485 // Signal handlers
486 // ------------------------------------------------------------------------
487
488 @TmfSignalHandler
489 @Override
490 public void traceClosed(final TmfTraceClosedSignal signal) {
491 super.traceClosed(signal);
492 synchronized (fSSEntryListMap) {
493 for (ITmfStateSystem ss : fTraceSSMap.removeAll(signal.getTrace())) {
494 fSSEntryListMap.remove(ss);
495 }
496 }
497 }
498}
This page took 0.052053 seconds and 5 git commands to generate.