tmf: Fix Select Traces command does not refresh trace type
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTraceManager.java
CommitLineData
fc526aef 1/*******************************************************************************
be4a197a 2 * Copyright (c) 2013, 2014 Ericsson
fc526aef
AM
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 * Alexandre Montplaisir - Initial API and implementation
0fcf3b09 11 * Patrick Tasse - Support selection range
d3de0920 12 * Xavier Raynaud - Support filters tracking
fc526aef
AM
13 *******************************************************************************/
14
15package org.eclipse.linuxtools.tmf.core.trace;
16
e1385db9 17import java.io.File;
fab18d20 18import java.util.Collections;
fc526aef
AM
19import java.util.LinkedHashMap;
20import java.util.Map;
fab18d20 21import java.util.Set;
fc526aef 22
deaae6e1 23import org.eclipse.core.resources.IFile;
e1385db9
AM
24import org.eclipse.core.resources.IResource;
25import org.eclipse.core.runtime.CoreException;
26import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
d3de0920
XR
27import org.eclipse.linuxtools.tmf.core.filter.ITmfFilter;
28import org.eclipse.linuxtools.tmf.core.signal.TmfEventFilterAppliedSignal;
fc526aef
AM
29import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
30import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
31import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
32import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
33import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
34import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
35import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
36import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
37import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
38import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
39
40/**
41 * Central trace manager for TMF. It tracks the currently opened traces and
0fcf3b09 42 * experiment, as well as the currently-selected time or time range and the
d3de0920
XR
43 * current window time range for each one of those. It also tracks filters
44 * applied for each trace.
fc526aef
AM
45 *
46 * It's a singleton class, so only one instance should exist (available via
47 * {@link #getInstance()}).
48 *
49 * @author Alexandre Montplaisir
50 * @since 2.0
51 */
52public final class TmfTraceManager {
53
54 // ------------------------------------------------------------------------
55 // Attributes
56 // ------------------------------------------------------------------------
57
58 private final Map<ITmfTrace, TmfTraceContext> fTraces;
59
60 /** The currently-selected trace. Should always be part of the trace map */
61 private ITmfTrace fCurrentTrace = null;
62
63 // ------------------------------------------------------------------------
64 // Constructor
65 // ------------------------------------------------------------------------
66
67 private TmfTraceManager() {
a4524c1b 68 fTraces = new LinkedHashMap<>();
fc526aef
AM
69 TmfSignalManager.registerVIP(this);
70 }
71
72 /** Singleton instance */
73 private static TmfTraceManager tm = null;
74
75 /**
76 * Get an instance of the trace manager.
77 *
78 * @return The trace manager
79 */
80 public static synchronized TmfTraceManager getInstance() {
81 if (tm == null) {
82 tm = new TmfTraceManager();
83 }
84 return tm;
85 }
86
87 // ------------------------------------------------------------------------
88 // Accessors
89 // ------------------------------------------------------------------------
90
fc526aef 91 /**
0fcf3b09 92 * @return The begin timestamp of selection
4b121c48 93 * @since 2.1
0fcf3b09
PT
94 */
95 public ITmfTimestamp getSelectionBeginTime() {
96 return getCurrentTraceContext().getSelectionBegin();
97 }
98
99 /**
100 * @return The end timestamp of selection
4b121c48 101 * @since 2.1
0fcf3b09
PT
102 */
103 public ITmfTimestamp getSelectionEndTime() {
104 return getCurrentTraceContext().getSelectionEnd();
105 }
106
107 /**
108 * Return the current window time range.
fc526aef 109 *
0fcf3b09 110 * @return the current window time range
fc526aef
AM
111 */
112 public synchronized TmfTimeRange getCurrentRange() {
0fcf3b09 113 return getCurrentTraceContext().getWindowRange();
fc526aef
AM
114 }
115
d3de0920
XR
116 /**
117 * Gets the filter applied to the current trace
118 *
119 * @return
120 * a filter, or <code>null</code>
121 * @since 2.2
122 */
123 public synchronized ITmfFilter getCurrentFilter() {
124 return getCurrentTraceContext().getFilter();
125 }
126
fc526aef
AM
127 /**
128 * Get the currently selected trace (normally, the focused editor).
129 *
130 * @return The active trace
131 */
132 public synchronized ITmfTrace getActiveTrace() {
133 return fCurrentTrace;
134 }
135
136 /**
a6fc3a28 137 * Get the trace set of the currently active trace.
fc526aef
AM
138 *
139 * @return The active trace set
a6fc3a28 140 * @see #getTraceSet(ITmfTrace)
fc526aef
AM
141 */
142 public synchronized ITmfTrace[] getActiveTraceSet() {
143 final ITmfTrace trace = fCurrentTrace;
a6fc3a28 144 return getTraceSet(trace);
fc526aef
AM
145 }
146
fab18d20
AM
147 /**
148 * Get the currently-opened traces, as an unmodifiable set.
149 *
150 * @return A set containing the opened traces
151 */
152 public synchronized Set<ITmfTrace> getOpenedTraces() {
153 return Collections.unmodifiableSet(fTraces.keySet());
154 }
155
deaae6e1
PT
156 /**
157 * Get the editor file for an opened trace.
158 *
159 * @param trace
160 * the trace
161 * @return the editor file or null if the trace is not opened
162 * @since 3.0
163 */
164 public synchronized IFile getTraceEditorFile(ITmfTrace trace) {
165 TmfTraceContext ctx = fTraces.get(trace);
166 if (ctx != null) {
167 return ctx.getEditorFile();
168 }
169 return null;
170 }
171
fc526aef
AM
172 private TmfTraceContext getCurrentTraceContext() {
173 TmfTraceContext curCtx = fTraces.get(fCurrentTrace);
174 if (curCtx == null) {
175 /* There are no traces opened at the moment. */
176 return TmfTraceContext.NULL_CONTEXT;
177 }
178 return curCtx;
179 }
180
e1385db9
AM
181 // ------------------------------------------------------------------------
182 // Public utility methods
183 // ------------------------------------------------------------------------
184
a6fc3a28
AM
185 /**
186 * Get the trace set of a given trace. For a standard trace, this is simply
187 * an array with only that trace in it. For experiments, this is an array of
188 * all the traces contained in this experiment.
189 *
190 * @param trace
191 * The trace or experiment
192 * @return The corresponding trace set
193 */
194 public static ITmfTrace[] getTraceSet(ITmfTrace trace) {
195 if (trace == null) {
196 return null;
197 }
198 if (trace instanceof TmfExperiment) {
199 TmfExperiment exp = (TmfExperiment) trace;
200 return exp.getTraces();
201 }
202 return new ITmfTrace[] { trace };
203 }
204
e1385db9
AM
205 /**
206 * Return the path (as a string) to the directory for supplementary files to
207 * use with a given trace. If no supplementary file directory has been
208 * configured, a temporary directory based on the trace's name will be
209 * provided.
210 *
211 * @param trace
212 * The trace
213 * @return The path to the supplementary file directory (trailing slash is
214 * INCLUDED!)
215 */
216 public static String getSupplementaryFileDir(ITmfTrace trace) {
217 IResource resource = trace.getResource();
218 if (resource == null) {
219 return getTemporaryDir(trace);
220 }
221
222 String supplDir = null;
223 try {
224 supplDir = resource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
225 } catch (CoreException e) {
226 return getTemporaryDir(trace);
227 }
228 return supplDir + File.separator;
229 }
230
fc526aef
AM
231 // ------------------------------------------------------------------------
232 // Signal handlers
233 // ------------------------------------------------------------------------
234
235 /**
236 * Signal handler for the traceOpened signal.
237 *
238 * @param signal
239 * The incoming signal
240 */
241 @TmfSignalHandler
242 public synchronized void traceOpened(final TmfTraceOpenedSignal signal) {
243 final ITmfTrace trace = signal.getTrace();
deaae6e1 244 final IFile editorFile = signal.getEditorFile();
fc526aef
AM
245 final ITmfTimestamp startTs = trace.getStartTime();
246
247 /* Calculate the initial time range */
248 final int SCALE = ITmfTimestamp.NANOSECOND_SCALE;
249 long offset = trace.getInitialRangeOffset().normalize(0, SCALE).getValue();
250 long endTime = startTs.normalize(0, SCALE).getValue() + offset;
251 final TmfTimeRange startTr = new TmfTimeRange(startTs, new TmfTimestamp(endTime, SCALE));
252
deaae6e1 253 final TmfTraceContext startCtx = new TmfTraceContext(startTs, startTs, startTr, editorFile);
fc526aef
AM
254
255 fTraces.put(trace, startCtx);
256
257 /* We also want to set the newly-opened trace as the active trace */
258 fCurrentTrace = trace;
259 }
260
261
262 /**
263 * Handler for the TmfTraceSelectedSignal.
264 *
265 * @param signal
266 * The incoming signal
267 */
268 @TmfSignalHandler
269 public synchronized void traceSelected(final TmfTraceSelectedSignal signal) {
270 final ITmfTrace newTrace = signal.getTrace();
271 if (!fTraces.containsKey(newTrace)) {
272 throw new RuntimeException();
273 }
274 fCurrentTrace = newTrace;
275 }
276
d3de0920
XR
277 /**
278 * Signal handler for the filterApplied signal.
279 *
280 * @param signal
281 * The incoming signal
282 * @since 2.2
283 */
284 @TmfSignalHandler
285 public synchronized void filterApplied(TmfEventFilterAppliedSignal signal) {
286 final ITmfTrace newTrace = signal.getTrace();
287 TmfTraceContext context = fTraces.get(newTrace);
288 if (context == null) {
289 throw new RuntimeException();
290 }
291 fTraces.put(newTrace, new TmfTraceContext(context, signal.getEventFilter()));
292 }
293
fc526aef
AM
294 /**
295 * Signal handler for the traceClosed signal.
296 *
297 * @param signal
298 * The incoming signal
299 */
300 @TmfSignalHandler
301 public synchronized void traceClosed(final TmfTraceClosedSignal signal) {
3fcf269e 302 fTraces.remove(signal.getTrace());
fc526aef
AM
303 if (fTraces.size() == 0) {
304 fCurrentTrace = null;
305 /*
306 * In other cases, we should receive a traceSelected signal that
307 * will indicate which trace is the new one.
308 */
309 }
310 }
311
312 /**
313 * Signal handler for the TmfTimeSynchSignal signal.
314 *
315 * The current time of *all* traces whose range contains the requested new
0fcf3b09 316 * selection time range will be updated.
fc526aef
AM
317 *
318 * @param signal
319 * The incoming signal
320 */
321 @TmfSignalHandler
322 public synchronized void timeUpdated(final TmfTimeSynchSignal signal) {
0fcf3b09
PT
323 final ITmfTimestamp beginTs = signal.getBeginTime();
324 final ITmfTimestamp endTs = signal.getEndTime();
fc526aef
AM
325
326 for (Map.Entry<ITmfTrace, TmfTraceContext> entry : fTraces.entrySet()) {
327 final ITmfTrace trace = entry.getKey();
0fcf3b09 328 if (beginTs.intersects(getValidTimeRange(trace)) || endTs.intersects(getValidTimeRange(trace))) {
fc526aef 329 TmfTraceContext prevCtx = entry.getValue();
0fcf3b09 330 TmfTraceContext newCtx = new TmfTraceContext(prevCtx, beginTs, endTs);
fc526aef
AM
331 entry.setValue(newCtx);
332 }
333 }
334 }
335
336 /**
337 * Signal handler for the TmfRangeSynchSignal signal.
338 *
0fcf3b09 339 * The current window time range of *all* valid traces will be updated
fc526aef
AM
340 * to the new requested times.
341 *
342 * @param signal
343 * The incoming signal
344 */
345 @TmfSignalHandler
346 public synchronized void timeRangeUpdated(final TmfRangeSynchSignal signal) {
fc526aef
AM
347 for (Map.Entry<ITmfTrace, TmfTraceContext> entry : fTraces.entrySet()) {
348 final ITmfTrace trace = entry.getKey();
349 final TmfTraceContext curCtx = entry.getValue();
350
351 final TmfTimeRange validTr = getValidTimeRange(trace);
352
fc526aef
AM
353 /* Determine the new time range */
354 TmfTimeRange targetTr = signal.getCurrentRange().getIntersection(validTr);
0fcf3b09 355 TmfTimeRange newTr = (targetTr == null ? curCtx.getWindowRange() : targetTr);
fc526aef
AM
356
357 /* Update the values */
0fcf3b09 358 TmfTraceContext newCtx = new TmfTraceContext(curCtx, newTr);
fc526aef
AM
359 entry.setValue(newCtx);
360 }
361 }
362
363 // ------------------------------------------------------------------------
e1385db9 364 // Private utility methods
fc526aef
AM
365 // ------------------------------------------------------------------------
366
367 /**
0fcf3b09
PT
368 * Return the valid time range of a trace (not the current window time
369 * range, but the range of all possible valid timestamps).
fc526aef
AM
370 *
371 * For a real trace this is the whole range of the trace. For an experiment,
372 * it goes from the start time of the earliest trace to the end time of the
373 * latest one.
374 *
375 * @param trace
376 * The trace to check for
377 * @return The valid time span, or 'null' if the trace is not valid
378 */
379 private TmfTimeRange getValidTimeRange(ITmfTrace trace) {
380 if (!fTraces.containsKey(trace)) {
381 /* Trace is not part of the currently opened traces */
382 return null;
383 }
384 if (!(trace instanceof TmfExperiment)) {
385 /* "trace" is a single trace, return its time range directly */
386 return trace.getTimeRange();
387 }
388 final ITmfTrace[] traces = ((TmfExperiment) trace).getTraces();
389 if (traces.length == 0) {
390 /* We are being trolled */
391 return null;
392 }
393 if (traces.length == 1) {
394 /* Trace is an experiment with only 1 trace */
395 return traces[0].getTimeRange();
396 }
397 /*
398 * Trace is an experiment with 2+ traces, so get the earliest start and
399 * the latest end.
400 */
401 ITmfTimestamp start = traces[0].getStartTime();
402 ITmfTimestamp end = traces[0].getEndTime();
403 for (int i = 1; i < traces.length; i++) {
404 ITmfTrace curTrace = traces[i];
405 if (curTrace.getStartTime().compareTo(start) < 0) {
406 start = curTrace.getStartTime();
407 }
408 if (curTrace.getEndTime().compareTo(end) > 0) {
409 end = curTrace.getEndTime();
410 }
411 }
412 return new TmfTimeRange(start, end);
413 }
e1385db9
AM
414
415 /**
6e4358bd
AM
416 * Get a temporary directory based on a trace's name. We will create the
417 * directory if it doesn't exist, so that it's ready to be used.
e1385db9
AM
418 */
419 private static String getTemporaryDir(ITmfTrace trace) {
6e4358bd 420 String pathName = System.getProperty("java.io.tmpdir") + //$NON-NLS-1$
e1385db9
AM
421 File.separator +
422 trace.getName() +
423 File.separator;
6e4358bd
AM
424 File dir = new File(pathName);
425 if (!dir.exists()) {
426 dir.mkdirs();
427 }
428 return pathName;
e1385db9 429 }
fc526aef 430}
This page took 0.087841 seconds and 5 git commands to generate.