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