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