tmf: Add a getTraceSet() method to the trace manager
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTraceManager.java
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
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.core.trace;
14
15 import java.util.LinkedHashMap;
16 import java.util.Map;
17
18 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
19 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
20 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
21 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
22 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
23 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
24 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
25 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
26 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
27 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
28
29 /**
30 * Central trace manager for TMF. It tracks the currently opened traces and
31 * experiment, as well as the currently-selected timestamps and time ranges for
32 * each one of those.
33 *
34 * It's a singleton class, so only one instance should exist (available via
35 * {@link #getInstance()}).
36 *
37 * @author Alexandre Montplaisir
38 * @since 2.0
39 */
40 public final class TmfTraceManager {
41
42 // ------------------------------------------------------------------------
43 // Attributes
44 // ------------------------------------------------------------------------
45
46 private final Map<ITmfTrace, TmfTraceContext> fTraces;
47
48 /** The currently-selected trace. Should always be part of the trace map */
49 private ITmfTrace fCurrentTrace = null;
50
51 // ------------------------------------------------------------------------
52 // Constructor
53 // ------------------------------------------------------------------------
54
55 private TmfTraceManager() {
56 fTraces = new LinkedHashMap<ITmfTrace, TmfTraceContext>();
57 TmfSignalManager.registerVIP(this);
58 }
59
60 /** Singleton instance */
61 private static TmfTraceManager tm = null;
62
63 /**
64 * Get an instance of the trace manager.
65 *
66 * @return The trace manager
67 */
68 public static synchronized TmfTraceManager getInstance() {
69 if (tm == null) {
70 tm = new TmfTraceManager();
71 }
72 return tm;
73 }
74
75 // ------------------------------------------------------------------------
76 // Accessors
77 // ------------------------------------------------------------------------
78
79 /**
80 * Return the current selected time.
81 *
82 * @return the current time stamp
83 */
84 public synchronized ITmfTimestamp getCurrentTime() {
85 return getCurrentTraceContext().getTimestamp();
86 }
87
88 /**
89 * Return the current selected range.
90 *
91 * @return the current time range
92 */
93 public synchronized TmfTimeRange getCurrentRange() {
94 return getCurrentTraceContext().getTimerange();
95 }
96
97 /**
98 * Get the currently selected trace (normally, the focused editor).
99 *
100 * @return The active trace
101 */
102 public synchronized ITmfTrace getActiveTrace() {
103 return fCurrentTrace;
104 }
105
106 /**
107 * Get the trace set of the currently active trace.
108 *
109 * @return The active trace set
110 * @see #getTraceSet(ITmfTrace)
111 */
112 public synchronized ITmfTrace[] getActiveTraceSet() {
113 final ITmfTrace trace = fCurrentTrace;
114 return getTraceSet(trace);
115 }
116
117 private TmfTraceContext getCurrentTraceContext() {
118 TmfTraceContext curCtx = fTraces.get(fCurrentTrace);
119 if (curCtx == null) {
120 /* There are no traces opened at the moment. */
121 return TmfTraceContext.NULL_CONTEXT;
122 }
123 return curCtx;
124 }
125
126 /**
127 * Get the trace set of a given trace. For a standard trace, this is simply
128 * an array with only that trace in it. For experiments, this is an array of
129 * all the traces contained in this experiment.
130 *
131 * @param trace
132 * The trace or experiment
133 * @return The corresponding trace set
134 */
135 public static ITmfTrace[] getTraceSet(ITmfTrace trace) {
136 if (trace == null) {
137 return null;
138 }
139 if (trace instanceof TmfExperiment) {
140 TmfExperiment exp = (TmfExperiment) trace;
141 return exp.getTraces();
142 }
143 return new ITmfTrace[] { trace };
144 }
145
146 // ------------------------------------------------------------------------
147 // Signal handlers
148 // ------------------------------------------------------------------------
149
150 /**
151 * Signal handler for the traceOpened signal.
152 *
153 * @param signal
154 * The incoming signal
155 */
156 @TmfSignalHandler
157 public synchronized void traceOpened(final TmfTraceOpenedSignal signal) {
158 final ITmfTrace trace = signal.getTrace();
159 final ITmfTimestamp startTs = trace.getStartTime();
160
161 /* Calculate the initial time range */
162 final int SCALE = ITmfTimestamp.NANOSECOND_SCALE;
163 long offset = trace.getInitialRangeOffset().normalize(0, SCALE).getValue();
164 long endTime = startTs.normalize(0, SCALE).getValue() + offset;
165 final TmfTimeRange startTr = new TmfTimeRange(startTs, new TmfTimestamp(endTime, SCALE));
166
167 final TmfTraceContext startCtx = new TmfTraceContext(startTs, startTr);
168
169 fTraces.put(trace, startCtx);
170
171 /* We also want to set the newly-opened trace as the active trace */
172 fCurrentTrace = trace;
173 }
174
175
176 /**
177 * Handler for the TmfTraceSelectedSignal.
178 *
179 * @param signal
180 * The incoming signal
181 */
182 @TmfSignalHandler
183 public synchronized void traceSelected(final TmfTraceSelectedSignal signal) {
184 final ITmfTrace newTrace = signal.getTrace();
185 if (!fTraces.containsKey(newTrace)) {
186 throw new RuntimeException();
187 }
188 fCurrentTrace = newTrace;
189 }
190
191 /**
192 * Signal handler for the traceClosed signal.
193 *
194 * @param signal
195 * The incoming signal
196 */
197 @TmfSignalHandler
198 public synchronized void traceClosed(final TmfTraceClosedSignal signal) {
199 fTraces.remove(signal.getTrace());
200 if (fTraces.size() == 0) {
201 fCurrentTrace = null;
202 /*
203 * In other cases, we should receive a traceSelected signal that
204 * will indicate which trace is the new one.
205 */
206 }
207 }
208
209 /**
210 * Signal handler for the TmfTimeSynchSignal signal.
211 *
212 * The current time of *all* traces whose range contains the requested new
213 * time will be updated.
214 *
215 * @param signal
216 * The incoming signal
217 */
218 @TmfSignalHandler
219 public synchronized void timeUpdated(final TmfTimeSynchSignal signal) {
220 final ITmfTimestamp ts = signal.getCurrentTime();
221
222 for (Map.Entry<ITmfTrace, TmfTraceContext> entry : fTraces.entrySet()) {
223 final ITmfTrace trace = entry.getKey();
224 if (ts.intersects(getValidTimeRange(trace))) {
225 TmfTraceContext prevCtx = entry.getValue();
226 TmfTraceContext newCtx = new TmfTraceContext(prevCtx, ts);
227 entry.setValue(newCtx);
228 }
229 }
230 }
231
232 /**
233 * Signal handler for the TmfRangeSynchSignal signal.
234 *
235 * The current timestamp and timerange of *all* valid traces will be updated
236 * to the new requested times.
237 *
238 * @param signal
239 * The incoming signal
240 */
241 @TmfSignalHandler
242 public synchronized void timeRangeUpdated(final TmfRangeSynchSignal signal) {
243 final ITmfTimestamp signalTs = signal.getCurrentTime();
244
245 for (Map.Entry<ITmfTrace, TmfTraceContext> entry : fTraces.entrySet()) {
246 final ITmfTrace trace = entry.getKey();
247 final TmfTraceContext curCtx = entry.getValue();
248
249 final TmfTimeRange validTr = getValidTimeRange(trace);
250
251 /* Determine the new time stamp */
252 ITmfTimestamp newTs;
253 if (signalTs != null && signalTs.intersects(validTr)) {
254 newTs = signalTs;
255 } else {
256 newTs = curCtx.getTimestamp();
257 }
258
259 /* Determine the new time range */
260 TmfTimeRange targetTr = signal.getCurrentRange().getIntersection(validTr);
261 TmfTimeRange newTr = (targetTr == null ? curCtx.getTimerange() : targetTr);
262
263 /* Update the values */
264 TmfTraceContext newCtx = new TmfTraceContext(newTs, newTr);
265 entry.setValue(newCtx);
266 }
267 }
268
269 // ------------------------------------------------------------------------
270 // Utility methods
271 // ------------------------------------------------------------------------
272
273 /**
274 * Return the valid time range of a trace (not the "current time range", but
275 * the range of all possible valid timestamps).
276 *
277 * For a real trace this is the whole range of the trace. For an experiment,
278 * it goes from the start time of the earliest trace to the end time of the
279 * latest one.
280 *
281 * @param trace
282 * The trace to check for
283 * @return The valid time span, or 'null' if the trace is not valid
284 */
285 private TmfTimeRange getValidTimeRange(ITmfTrace trace) {
286 if (!fTraces.containsKey(trace)) {
287 /* Trace is not part of the currently opened traces */
288 return null;
289 }
290 if (!(trace instanceof TmfExperiment)) {
291 /* "trace" is a single trace, return its time range directly */
292 return trace.getTimeRange();
293 }
294 final ITmfTrace[] traces = ((TmfExperiment) trace).getTraces();
295 if (traces.length == 0) {
296 /* We are being trolled */
297 return null;
298 }
299 if (traces.length == 1) {
300 /* Trace is an experiment with only 1 trace */
301 return traces[0].getTimeRange();
302 }
303 /*
304 * Trace is an experiment with 2+ traces, so get the earliest start and
305 * the latest end.
306 */
307 ITmfTimestamp start = traces[0].getStartTime();
308 ITmfTimestamp end = traces[0].getEndTime();
309 for (int i = 1; i < traces.length; i++) {
310 ITmfTrace curTrace = traces[i];
311 if (curTrace.getStartTime().compareTo(start) < 0) {
312 start = curTrace.getStartTime();
313 }
314 if (curTrace.getEndTime().compareTo(end) > 0) {
315 end = curTrace.getEndTime();
316 }
317 }
318 return new TmfTimeRange(start, end);
319 }
320 }
This page took 0.039594 seconds and 5 git commands to generate.