Merge branch 'master' into lttng-luna
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / ctfadaptor / CtfTmfTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Updated for removal of context clone
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.tmf.core.ctfadaptor;
15
16 import java.nio.BufferOverflowException;
17 import java.util.Collections;
18 import java.util.Map;
19
20 import org.eclipse.core.resources.IProject;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24 import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
25 import org.eclipse.linuxtools.ctf.core.event.CTFClock;
26 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
27 import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
28 import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
29 import org.eclipse.linuxtools.internal.tmf.core.Activator;
30 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
31 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
32 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
33 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
34 import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
35 import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;
36 import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
37 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
38 import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
39
40 /**
41 * The CTf trace handler
42 *
43 * @version 1.0
44 * @author Matthew khouzam
45 */
46 public class CtfTmfTrace extends TmfTrace
47 implements ITmfEventParser, ITmfTraceProperties {
48
49 // -------------------------------------------
50 // Constants
51 // -------------------------------------------
52 /**
53 * Default cache size for CTF traces
54 */
55 protected static final int DEFAULT_CACHE_SIZE = 50000;
56
57 /*
58 * The Ctf clock unique identifier field
59 */
60 private static final String CLOCK_HOST_PROPERTY = "uuid"; //$NON-NLS-1$
61
62 // -------------------------------------------
63 // Fields
64 // -------------------------------------------
65
66 /* Reference to the CTF Trace */
67 private CTFTrace fTrace;
68
69 // -------------------------------------------
70 // TmfTrace Overrides
71 // -------------------------------------------
72 /**
73 * Method initTrace.
74 *
75 * @param resource
76 * The resource associated with this trace
77 * @param path
78 * The path to the trace file
79 * @param eventType
80 * The type of events that will be read from this trace
81 * @throws TmfTraceException
82 * If something when wrong while reading the trace
83 */
84 @Override
85 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType)
86 throws TmfTraceException {
87 /*
88 * Set the cache size. This has to be done before the call to super()
89 * because the super needs to know the cache size.
90 */
91 setCacheSize();
92
93 super.initTrace(resource, path, eventType);
94
95 try {
96 this.fTrace = new CTFTrace(path);
97 CtfIteratorManager.addTrace(this);
98 CtfTmfContext ctx;
99 /* Set the start and (current) end times for this trace */
100 ctx = (CtfTmfContext) seekEvent(0L);
101 CtfTmfEvent event = getNext(ctx);
102 if ((ctx.getLocation().equals(CtfIterator.NULL_LOCATION)) || (ctx.getCurrentEvent() == null)) {
103 /* Handle the case where the trace is empty */
104 this.setStartTime(TmfTimestamp.BIG_BANG);
105 } else {
106 final ITmfTimestamp curTime = event.getTimestamp();
107 this.setStartTime(curTime);
108 this.setEndTime(curTime);
109 }
110
111 } catch (final CTFReaderException e) {
112 /*
113 * If it failed at the init(), we can assume it's because the file
114 * was not found or was not recognized as a CTF trace. Throw into
115 * the new type of exception expected by the rest of TMF.
116 */
117 throw new TmfTraceException(e.getMessage(), e);
118 }
119 }
120
121 @Override
122 public synchronized void dispose() {
123 CtfIteratorManager.removeTrace(this);
124 if (fTrace != null) {
125 fTrace.dispose();
126 fTrace = null;
127 }
128 super.dispose();
129 }
130
131 /**
132 * Method validate.
133 *
134 * @param project
135 * IProject
136 * @param path
137 * String
138 * @return IStatus IStatus.error or Status.OK_STATUS
139 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(IProject, String)
140 * @since 2.0
141 */
142 @Override
143 public IStatus validate(final IProject project, final String path) {
144 IStatus validTrace = Status.OK_STATUS;
145 try {
146 final CTFTrace temp = new CTFTrace(path);
147 if (!temp.majortIsSet()) {
148 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_MajorNotSet);
149 } else {
150 CTFTraceReader ctfTraceReader = new CTFTraceReader(temp);
151 if (!ctfTraceReader.hasMoreEvents()) {
152 // TODO: This will need an additional check when we support live traces
153 // because having no event is valid for a live trace
154 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_NoEvent);
155 }
156 ctfTraceReader.dispose();
157 }
158 temp.dispose();
159 } catch (final CTFReaderException e) {
160 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError +": " + e.toString()); //$NON-NLS-1$
161 } catch (final BufferOverflowException e){
162 validTrace = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError +": " + Messages.CtfTmfTrace_BufferOverflowErrorMessage); //$NON-NLS-1$
163 }
164
165 return validTrace;
166 }
167
168 /**
169 * Method getCurrentLocation. This is not applicable in CTF
170 *
171 * @return null, since the trace has no knowledge of the current location
172 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getCurrentLocation()
173 * @since 3.0
174 */
175 @Override
176 public ITmfLocation getCurrentLocation() {
177 return null;
178 }
179
180 /**
181 * @since 3.0
182 */
183 @Override
184 public double getLocationRatio(ITmfLocation location) {
185 final CtfLocation curLocation = (CtfLocation) location;
186 final CtfTmfContext context = new CtfTmfContext(this);
187 context.setLocation(curLocation);
188 context.seek(curLocation.getLocationInfo());
189 final CtfLocationInfo currentTime = ((CtfLocationInfo) context.getLocation().getLocationInfo());
190 final long startTime = getIterator(this, context).getStartTime();
191 final long endTime = getIterator(this, context).getEndTime();
192 return ((double) currentTime.getTimestamp() - startTime)
193 / (endTime - startTime);
194 }
195
196 /**
197 * Method seekEvent.
198 *
199 * @param location
200 * ITmfLocation<?>
201 * @return ITmfContext
202 * @since 3.0
203 */
204 @Override
205 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
206 CtfLocation currentLocation = (CtfLocation) location;
207 CtfTmfContext context = new CtfTmfContext(this);
208 if (fTrace == null) {
209 context.setLocation(null);
210 context.setRank(ITmfContext.UNKNOWN_RANK);
211 return context;
212 }
213 /*
214 * The rank is set to 0 if the iterator seeks the beginning. If not, it
215 * will be set to UNKNOWN_RANK, since CTF traces don't support seeking
216 * by rank for now.
217 */
218 if (currentLocation == null) {
219 currentLocation = new CtfLocation(new CtfLocationInfo(0L, 0L));
220 context.setRank(0);
221 }
222 if (currentLocation.getLocationInfo() == CtfLocation.INVALID_LOCATION) {
223 currentLocation = new CtfLocation(getEndTime().getValue() + 1, 0L);
224 }
225 context.setLocation(currentLocation);
226 if (location == null) {
227 CtfTmfEvent event = getIterator(this, context).getCurrentEvent();
228 if (event != null) {
229 currentLocation = new CtfLocation(event.getTimestamp().getValue(), 0);
230 }
231 }
232 if (context.getRank() != 0) {
233 context.setRank(ITmfContext.UNKNOWN_RANK);
234 }
235 return context;
236 }
237
238 @Override
239 public synchronized ITmfContext seekEvent(double ratio) {
240 CtfTmfContext context = new CtfTmfContext(this);
241 if (fTrace == null) {
242 context.setLocation(null);
243 context.setRank(ITmfContext.UNKNOWN_RANK);
244 return context;
245 }
246 final long end = this.getEndTime().getValue();
247 final long start = this.getStartTime().getValue();
248 final long diff = end - start;
249 final long ratioTs = Math.round(diff * ratio) + start;
250 context.seek(ratioTs);
251 context.setRank(ITmfContext.UNKNOWN_RANK);
252 return context;
253 }
254
255 /**
256 * Method readNextEvent.
257 *
258 * @param context
259 * ITmfContext
260 * @return CtfTmfEvent
261 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNext(ITmfContext)
262 */
263 @Override
264 public synchronized CtfTmfEvent getNext(final ITmfContext context) {
265 if (fTrace == null) {
266 return null;
267 }
268 CtfTmfEvent event = null;
269 if (context instanceof CtfTmfContext) {
270 if (context.getLocation() == null || CtfLocation.INVALID_LOCATION.equals(context.getLocation().getLocationInfo())) {
271 return null;
272 }
273 CtfTmfContext ctfContext = (CtfTmfContext) context;
274 event = ctfContext.getCurrentEvent();
275
276 if (event != null) {
277 updateAttributes(context, event.getTimestamp());
278 ctfContext.advance();
279 ctfContext.increaseRank();
280 }
281 }
282
283 return event;
284 }
285
286 /**
287 * gets the CTFtrace that this is wrapping
288 *
289 * @return the CTF trace
290 */
291 public CTFTrace getCTFTrace() {
292 return fTrace;
293 }
294
295 /**
296 * Ctf traces have a clock with a unique uuid that will be used to identify
297 * the host. Traces with the same clock uuid will be known to have been made
298 * on the same machine.
299 *
300 * Note: uuid is an optional field, it may not be there for a clock.
301 */
302 @Override
303 public String getHostId() {
304 CTFClock clock = getCTFTrace().getClock();
305 if (clock != null) {
306 String clockHost = (String) clock.getProperty(CLOCK_HOST_PROPERTY);
307 if (clockHost != null) {
308 return clockHost;
309 }
310 }
311 return super.getHostId();
312 }
313
314 // -------------------------------------------
315 // ITmfTraceProperties
316 // -------------------------------------------
317
318 /**
319 * @since 2.0
320 */
321 @Override
322 public Map<String, String> getTraceProperties() {
323 return Collections.unmodifiableMap(fTrace.getEnvironment());
324 }
325
326 // -------------------------------------------
327 // Clocks
328 // -------------------------------------------
329
330 /**
331 * gets the clock offset
332 *
333 * @return the clock offset in ns
334 */
335 public long getOffset() {
336 if (fTrace != null) {
337 return fTrace.getOffset();
338 }
339 return 0;
340 }
341
342 /**
343 * Returns whether or not an event is in the metadata of the trace,
344 * therefore if it can possibly be in the trace. It does not verify whether
345 * or not the event is actually in the trace
346 *
347 * @param eventName
348 * The name of the event to check
349 * @return Whether the event is in the metadata or not
350 * @since 3.0
351 */
352 public boolean hasEvent(final String eventName) {
353 Map<Long, IEventDeclaration> events = fTrace.getEvents(0L);
354 if (events != null) {
355 for (IEventDeclaration decl : events.values()) {
356 if (decl.getName().equals(eventName)) {
357 return true;
358 }
359 }
360 }
361 return false;
362 }
363
364 /**
365 * Return whether all requested events are in the metadata
366 *
367 * @param names
368 * The array of events to check for
369 * @return Whether all events are in the metadata
370 * @since 3.0
371 */
372 public boolean hasAllEvents(String[] names) {
373 for (String name : names) {
374 if (!hasEvent(name)) {
375 return false;
376 }
377 }
378 return true;
379 }
380
381 /**
382 * Returns whether the metadata contains at least one of the requested
383 * events
384 *
385 * @param names
386 * The array of event names of check for
387 * @return Whether one of the event is present in trace metadata
388 * @since 3.0
389 */
390 public boolean hasAtLeastOneOfEvents(String[] names) {
391 for (String name : names) {
392 if (hasEvent(name)) {
393 return true;
394 }
395 }
396 return false;
397 }
398
399 // -------------------------------------------
400 // Parser
401 // -------------------------------------------
402
403 @Override
404 public CtfTmfEvent parseEvent(ITmfContext context) {
405 CtfTmfEvent event = null;
406 if (context instanceof CtfTmfContext) {
407 final ITmfContext tmpContext = seekEvent(context.getLocation());
408 event = getNext(tmpContext);
409 }
410 return event;
411 }
412
413 /**
414 * Sets the cache size for a CtfTmfTrace.
415 */
416 protected void setCacheSize() {
417 setCacheSize(DEFAULT_CACHE_SIZE);
418 }
419
420 // -------------------------------------------
421 // Helpers
422 // -------------------------------------------
423
424 private static CtfIterator getIterator(CtfTmfTrace trace, CtfTmfContext context) {
425 return CtfIteratorManager.getIterator(trace, context);
426 }
427
428 /**
429 * Get an iterator to the trace
430 *
431 * @return an iterator to the trace
432 * @since 2.0
433 */
434 public CtfIterator createIterator() {
435 return new CtfIterator(this);
436 }
437 }
This page took 0.053202 seconds and 6 git commands to generate.