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