Change some @since to 1.1 for things that were really added in 1.1
[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
101 public void run() {
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);
e790b877 118 getTimeGraphViewer().getTimeGraphControl().setMarkers(markers);
6ae6c5bd
PT
119 }
120 }
121
122 @Override
123 public void cancel() {
124 super.cancel();
125 if (fClearZoomedLists) {
126 clearZoomedLists();
127 }
128 }
129
e790b877 130 private void zoomByTime(final ITmfStateSystem ss, final List<TimeGraphEntry> entryList, final List<ILinkEvent> links, final List<IMarkerEvent> markers,
6ae6c5bd
PT
131 long startTime, long endTime, long resolution, final @NonNull IProgressMonitor monitor) {
132 final long start = Math.max(startTime, ss.getStartTime());
133 final long end = Math.min(endTime, ss.getCurrentEndTime());
134 final boolean fullRange = getZoomStartTime() <= getStartTime() && getZoomEndTime() >= getEndTime();
135 if (end < start) {
136 return;
137 }
138 if (fullRange) {
139 redraw();
140 }
141 queryFullStates(ss, start, end, resolution, monitor, new IQueryHandler() {
142 @Override
143 public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
144 if (!fullRange) {
145 for (TimeGraphEntry entry : entryList) {
146 zoom(checkNotNull(entry), ss, fullStates, prevFullState, monitor);
147 }
148 }
149 /* Refresh the arrows when zooming */
150 links.addAll(getLinkList(ss, fullStates, monitor));
e790b877
PT
151 /* Refresh the markers when zooming */
152 markers.addAll(getMarkerList(ss, fullStates, monitor));
6ae6c5bd
PT
153 }
154 });
155 refresh();
156 }
157
158 private void zoom(@NonNull TimeGraphEntry entry, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
159 List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
160 if (eventList != null) {
161 for (ITimeEvent event : eventList) {
162 entry.addZoomedEvent(event);
163 }
164 }
165 for (ITimeGraphEntry child : entry.getChildren()) {
166 if (monitor.isCanceled()) {
167 return;
168 }
169 if (child instanceof TimeGraphEntry) {
170 zoom((TimeGraphEntry) child, ss, fullStates, prevFullState, monitor);
171 }
172 }
173 }
174
175 private void clearZoomedLists() {
176 for (ITmfStateSystem ss : fZoomSSList) {
177 List<TimeGraphEntry> entryList = null;
178 synchronized (fSSEntryListMap) {
179 entryList = fSSEntryListMap.get(ss);
180 }
181 if (entryList != null) {
182 for (TimeGraphEntry entry : entryList) {
183 clearZoomedList(entry);
184 }
185 }
186 }
187 fClearZoomedLists = false;
188 }
189
190 private void clearZoomedList(TimeGraphEntry entry) {
191 entry.setZoomedEventList(null);
192 for (ITimeGraphEntry child : entry.getChildren()) {
193 if (child instanceof TimeGraphEntry) {
194 clearZoomedList((TimeGraphEntry) child);
195 }
196 }
197 }
198 }
199
200 // ------------------------------------------------------------------------
201 // Constructors
202 // ------------------------------------------------------------------------
203
204 /**
205 * Constructs a time graph view that contains either a time graph viewer or
206 * a time graph combo.
207 *
208 * By default, the view uses a time graph viewer. To use a time graph combo,
209 * the subclass constructor must call {@link #setTreeColumns(String[])} and
210 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
211 *
212 * @param id
213 * The id of the view
214 * @param pres
215 * The presentation provider
216 */
217 public AbstractStateSystemTimeGraphView(String id, TimeGraphPresentationProvider pres) {
218 super(id, pres);
219 }
220
221 // ------------------------------------------------------------------------
222 // Internal
223 // ------------------------------------------------------------------------
224
225 /**
226 * Gets the entry list for a state system
227 *
228 * @param ss
229 * the state system
230 *
231 * @return the entry list map
232 */
233 protected List<TimeGraphEntry> getEntryList(ITmfStateSystem ss) {
234 synchronized (fSSEntryListMap) {
235 return fSSEntryListMap.get(ss);
236 }
237 }
238
239 /**
240 * Adds a trace entry list to the entry list map
241 *
242 * @param trace
243 * the trace
244 * @param ss
245 * the state system
246 * @param list
247 * the list of time graph entries
248 */
249 protected void putEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
250 super.putEntryList(trace, list);
251 synchronized (fSSEntryListMap) {
252 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
253 fTraceSSMap.put(trace, ss);
254 }
255 }
256
257 /**
258 * Adds a list of entries to a trace's entry list
259 *
260 * @param trace
261 * the trace
262 * @param ss
263 * the state system
264 * @param list
265 * the list of time graph entries to add
266 */
267 protected void addToEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
268 super.addToEntryList(trace, list);
269 synchronized (fSSEntryListMap) {
270 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
271 if (entryList == null) {
272 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
273 } else {
274 entryList.addAll(list);
275 }
276 fTraceSSMap.put(trace, ss);
277 }
278 }
279
280 /**
281 * Removes a list of entries from a trace's entry list
282 *
283 * @param trace
284 * the trace
285 * @param ss
286 * the state system
287 * @param list
288 * the list of time graph entries to remove
289 */
290 protected void removeFromEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
291 super.removeFromEntryList(trace, list);
292 synchronized (fSSEntryListMap) {
293 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
294 if (entryList != null) {
295 entryList.removeAll(list);
296 if (entryList.isEmpty()) {
297 fTraceSSMap.remove(trace, ss);
298 }
299 }
300 }
301 }
302
303 @Override
304 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
305 List<ITmfStateSystem> ssList = null;
306 synchronized (fSSEntryListMap) {
307 ssList = new ArrayList<>(fTraceSSMap.get(getTrace()));
308 }
309 if (ssList.isEmpty()) {
310 return null;
311 }
312 return new ZoomThreadByTime(ssList, startTime, endTime, resolution, restart);
313 }
314
315 /**
316 * Query the state system full state for the given time range.
317 *
318 * @param ss
319 * The state system
320 * @param start
321 * The start time
322 * @param end
323 * The end time
324 * @param resolution
325 * The resolution
326 * @param monitor
327 * The progress monitor
328 * @param handler
329 * The query handler
330 */
331 protected void queryFullStates(ITmfStateSystem ss, long start, long end, long resolution,
332 @NonNull IProgressMonitor monitor, @NonNull IQueryHandler handler) {
333 List<List<ITmfStateInterval>> fullStates = new ArrayList<>();
334 List<ITmfStateInterval> prevFullState = null;
335 try {
336 long time = start;
337 while (true) {
338 if (monitor.isCanceled()) {
339 break;
340 }
341 List<ITmfStateInterval> fullState = ss.queryFullState(time);
342 fullStates.add(fullState);
343 if (fullStates.size() * fullState.size() > MAX_INTERVALS) {
344 handler.handle(fullStates, prevFullState);
345 prevFullState = fullStates.get(fullStates.size() - 1);
346 fullStates.clear();
347 }
348 if (time >= end) {
349 break;
350 }
351 time = Math.min(end, time + resolution);
352 }
353 if (fullStates.size() > 0) {
354 handler.handle(fullStates, prevFullState);
355 }
356 } catch (StateSystemDisposedException e) {
357 /* Ignored */
358 }
359 }
360
361 /**
362 * Gets the list of events for an entry for a given list of full states.
363 *
364 * @param tgentry
365 * The time graph entry
366 * @param ss
367 * The state system
368 * @param fullStates
369 * A list of full states
370 * @param prevFullState
371 * The previous full state, or null
372 * @param monitor
373 * A progress monitor
374 * @return The list of time graph events
6ae6c5bd
PT
375 */
376 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
377 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor);
378
379 /**
380 * Gets the list of links (displayed as arrows) for a given list of full
381 * states. The default implementation returns an empty list.
382 *
383 * @param ss
384 * The state system
385 * @param fullStates
386 * A list of full states
387 * @param monitor
388 * A progress monitor
389 * @return The list of link events
390 */
391 protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
392 @NonNull List<List<ITmfStateInterval>> fullStates, @NonNull IProgressMonitor monitor) {
393 return new ArrayList<>();
394 }
395
e790b877
PT
396 /**
397 * Gets the list of markers for a given list of full
398 * states. The default implementation returns an empty list.
399 *
400 * @param ss
401 * The state system
402 * @param fullStates
403 * A list of full states
404 * @param monitor
405 * A progress monitor
406 * @return The list of marker events
5dd0ebfe 407 * @since 2.0
e790b877
PT
408 */
409 protected @NonNull List<IMarkerEvent> getMarkerList(ITmfStateSystem ss,
410 @NonNull List<List<ITmfStateInterval>> fullStates, @NonNull IProgressMonitor monitor) {
411 return new ArrayList<>();
412 }
413
6ae6c5bd
PT
414 /**
415 * @deprecated The subclass should call {@link #getEntryList(ITmfStateSystem)} instead.
416 */
417 @Deprecated
418 @Override
419 protected final List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
420 throw new UnsupportedOperationException();
421 }
422
423 /**
424 * @deprecated The subclass should call {@link #addToEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
425 */
426 @Deprecated
427 @Override
428 protected final void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
429 throw new UnsupportedOperationException();
430 }
431
432 /**
433 * @deprecated The subclass should call {@link #putEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
434 */
435 @Deprecated
436 @Override
437 protected final void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
438 throw new UnsupportedOperationException();
439 }
440
441 /**
442 * @deprecated The subclass should call {@link #removeFromEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
443 */
444 @Deprecated
445 @Override
446 protected final void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
447 throw new UnsupportedOperationException();
448 }
449
450 /**
451 * @deprecated The subclass should implement {@link #getEventList(TimeGraphEntry, ITmfStateSystem, List, List, IProgressMonitor)} instead.
452 */
453 @Deprecated
454 @Override
455 protected final List<ITimeEvent> getEventList(TimeGraphEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
456 throw new UnsupportedOperationException();
457 }
458
459 /**
460 * @deprecated The subclass should implement {@link #getLinkList(ITmfStateSystem, List, IProgressMonitor)} instead.
461 */
462 @Deprecated
463 @Override
464 protected final List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
465 throw new UnsupportedOperationException();
466 }
467
e790b877
PT
468 /**
469 * @deprecated The subclass should implement {@link #getMarkerList(ITmfStateSystem, List, IProgressMonitor)} instead.
470 */
471 @Deprecated
472 @Override
473 protected final List<IMarkerEvent> getMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
474 throw new UnsupportedOperationException();
475 }
476
6ae6c5bd
PT
477 // ------------------------------------------------------------------------
478 // Signal handlers
479 // ------------------------------------------------------------------------
480
481 @TmfSignalHandler
482 @Override
483 public void traceClosed(final TmfTraceClosedSignal signal) {
484 super.traceClosed(signal);
485 synchronized (fSSEntryListMap) {
486 for (ITmfStateSystem ss : fTraceSSMap.removeAll(signal.getTrace())) {
487 fSSEntryListMap.remove(ss);
488 }
489 }
490 }
491}
This page took 0.076143 seconds and 5 git commands to generate.