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