tmf: Rename packages to org.eclipse.tracecompass.*
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ctf.core / src / org / eclipse / tracecompass / tmf / ctf / core / CtfTmfTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 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.tracecompass.tmf.ctf.core;
16
17 import java.nio.BufferOverflowException;
18 import java.nio.ByteBuffer;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24
25 import org.eclipse.core.resources.IProject;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IStatus;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.linuxtools.ctf.core.event.CTFClock;
31 import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
32 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
33 import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
34 import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
35 import org.eclipse.tracecompass.internal.tmf.ctf.core.Activator;
36 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
37 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
38 import org.eclipse.tracecompass.tmf.core.event.ITmfEventType;
39 import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
40 import org.eclipse.tracecompass.tmf.core.event.TmfEventTypeManager;
41 import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
42 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
43 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
44 import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
45 import org.eclipse.tracecompass.tmf.core.trace.ITmfEventParser;
46 import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceProperties;
47 import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
48 import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
49 import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
50 import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
51 import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer;
52 import org.eclipse.tracecompass.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
53 import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
54 import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
55 import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
56
57 import com.google.common.collect.ImmutableSet;
58
59 /**
60 * The CTf trace handler
61 *
62 * @version 1.0
63 * @author Matthew khouzam
64 */
65 public class CtfTmfTrace extends TmfTrace
66 implements ITmfEventParser, ITmfTraceProperties, ITmfPersistentlyIndexable,
67 ITmfTraceWithPreDefinedEvents, AutoCloseable {
68
69 // -------------------------------------------
70 // Constants
71 // -------------------------------------------
72 /**
73 * Default cache size for CTF traces
74 */
75 protected static final int DEFAULT_CACHE_SIZE = 50000;
76
77 /*
78 * The Ctf clock unique identifier field
79 */
80 private static final String CLOCK_HOST_PROPERTY = "uuid"; //$NON-NLS-1$
81 private static final int CONFIDENCE = 10;
82
83 // -------------------------------------------
84 // Fields
85 // -------------------------------------------
86
87 /* Reference to the CTF Trace */
88 private CTFTrace fTrace;
89
90 // -------------------------------------------
91 // TmfTrace Overrides
92 // -------------------------------------------
93 /**
94 * Method initTrace.
95 *
96 * @param resource
97 * The resource associated with this trace
98 * @param path
99 * The path to the trace file
100 * @param eventType
101 * The type of events that will be read from this trace
102 * @throws TmfTraceException
103 * If something went wrong while reading the trace
104 */
105 @Override
106 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType)
107 throws TmfTraceException {
108 /*
109 * Set the cache size. This has to be done before the call to super()
110 * because the super needs to know the cache size.
111 */
112 setCacheSize();
113
114 super.initTrace(resource, path, eventType);
115
116 try {
117 this.fTrace = new CTFTrace(path);
118 CtfIteratorManager.addTrace(this);
119 CtfTmfContext ctx;
120 /* Set the start and (current) end times for this trace */
121 ctx = (CtfTmfContext) seekEvent(0L);
122 CtfTmfEvent event = getNext(ctx);
123 if ((ctx.getLocation().equals(CtfIterator.NULL_LOCATION)) || (ctx.getCurrentEvent() == null)) {
124 /* Handle the case where the trace is empty */
125 this.setStartTime(TmfTimestamp.BIG_BANG);
126 } else {
127 final ITmfTimestamp curTime = event.getTimestamp();
128 this.setStartTime(curTime);
129 this.setEndTime(curTime);
130 }
131 /*
132 * Register every event type. When you call getType, it will
133 * register a trace to that type in the TmfEventTypeManager
134 */
135 try (CtfIterator iter = CtfIteratorManager.getIterator(this, ctx)) {
136 for (IEventDeclaration ied : iter.getEventDeclarations()) {
137 CtfTmfEventType ctfTmfEventType = CtfTmfEventType.get(this, ied.getName());
138 if (ctfTmfEventType == null) {
139 List<ITmfEventField> content = new ArrayList<>();
140 /* Should only return null the first time */
141 for (String fieldName : ied.getFields().getFieldsList()) {
142 content.add(new TmfEventField(fieldName, null, null));
143 }
144 ITmfEventField contentTree = new TmfEventField(
145 ITmfEventField.ROOT_FIELD_ID,
146 null,
147 content.toArray(new ITmfEventField[content.size()])
148 );
149
150 ctfTmfEventType = new CtfTmfEventType(ied.getName(), this, contentTree);
151 }
152 }
153 }
154 } catch (final CTFReaderException e) {
155 /*
156 * If it failed at the init(), we can assume it's because the file
157 * was not found or was not recognized as a CTF trace. Throw into
158 * the new type of exception expected by the rest of TMF.
159 */
160 throw new TmfTraceException(e.getMessage(), e);
161 }
162 }
163
164 @Override
165 public void close() {
166 dispose();
167 }
168
169 @Override
170 public synchronized void dispose() {
171 CtfIteratorManager.removeTrace(this);
172 if (fTrace != null) {
173 fTrace.close();
174 fTrace = null;
175 }
176 super.dispose();
177 }
178
179 /**
180 * {@inheritDoc}
181 * <p>
182 * The default implementation sets the confidence to 10 if the trace is a
183 * valid CTF trace.
184 */
185 @Override
186 public IStatus validate(final IProject project, final String path) {
187 IStatus status = new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
188 try (final CTFTrace temp = new CTFTrace(path);) {
189 if (!temp.majorIsSet()) {
190 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_MajorNotSet);
191 } else {
192 try (CTFTraceReader ctfTraceReader = new CTFTraceReader(temp);) {
193 if (!ctfTraceReader.hasMoreEvents()) {
194 // TODO: This will need an additional check when we
195 // support live traces
196 // because having no event is valid for a live trace
197 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_NoEvent);
198 }
199 }
200 }
201 } catch (final CTFReaderException e) {
202 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError + ": " + e.toString()); //$NON-NLS-1$
203 } catch (final BufferOverflowException e) {
204 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError + ": " + Messages.CtfTmfTrace_BufferOverflowErrorMessage); //$NON-NLS-1$
205 }
206
207 return status;
208 }
209
210 /**
211 * Method getCurrentLocation. This is not applicable in CTF
212 *
213 * @return null, since the trace has no knowledge of the current location
214 * @see org.eclipse.tracecompass.tmf.core.trace.ITmfTrace#getCurrentLocation()
215 * @since 3.0
216 */
217 @Override
218 public ITmfLocation getCurrentLocation() {
219 return null;
220 }
221
222 /**
223 * @since 3.0
224 */
225 @Override
226 public double getLocationRatio(ITmfLocation location) {
227 final CtfLocation curLocation = (CtfLocation) location;
228 final CtfTmfContext context = new CtfTmfContext(this);
229 context.setLocation(curLocation);
230 context.seek(curLocation.getLocationInfo());
231 final CtfLocationInfo currentTime = ((CtfLocationInfo) context.getLocation().getLocationInfo());
232 final long startTime = getIterator(this, context).getStartTime();
233 final long endTime = getIterator(this, context).getEndTime();
234 return ((double) currentTime.getTimestamp() - startTime)
235 / (endTime - startTime);
236 }
237
238 /**
239 * Method seekEvent.
240 *
241 * @param location
242 * ITmfLocation<?>
243 * @return ITmfContext
244 * @since 3.0
245 */
246 @Override
247 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
248 CtfLocation currentLocation = (CtfLocation) location;
249 CtfTmfContext context = new CtfTmfContext(this);
250 if (fTrace == null) {
251 context.setLocation(null);
252 context.setRank(ITmfContext.UNKNOWN_RANK);
253 return context;
254 }
255 /*
256 * The rank is set to 0 if the iterator seeks the beginning. If not, it
257 * will be set to UNKNOWN_RANK, since CTF traces don't support seeking
258 * by rank for now.
259 */
260 if (currentLocation == null) {
261 currentLocation = new CtfLocation(new CtfLocationInfo(0L, 0L));
262 context.setRank(0);
263 }
264 if (currentLocation.getLocationInfo() == CtfLocation.INVALID_LOCATION) {
265 currentLocation = new CtfLocation(getCTFTrace().getCurrentEndTime() + 1, 0L);
266 }
267 context.setLocation(currentLocation);
268 if (location == null) {
269 long timestamp = getIterator(this, context).getCurrentTimestamp();
270 currentLocation = new CtfLocation(timestamp, 0);
271 }
272 if (context.getRank() != 0) {
273 context.setRank(ITmfContext.UNKNOWN_RANK);
274 }
275 return context;
276 }
277
278 @Override
279 public synchronized ITmfContext seekEvent(double ratio) {
280 CtfTmfContext context = new CtfTmfContext(this);
281 if (fTrace == null) {
282 context.setLocation(null);
283 context.setRank(ITmfContext.UNKNOWN_RANK);
284 return context;
285 }
286 final long end = getCTFTrace().getCurrentEndTime();
287 final long start = getCTFTrace().getCurrentStartTime();
288 final long diff = end - start;
289 final long ratioTs = Math.round(diff * ratio) + start;
290 context.seek(ratioTs);
291 context.setRank(ITmfContext.UNKNOWN_RANK);
292 return context;
293 }
294
295 /**
296 * Method readNextEvent.
297 *
298 * @param context
299 * ITmfContext
300 * @return CtfTmfEvent
301 * @see org.eclipse.tracecompass.tmf.core.trace.ITmfTrace#getNext(ITmfContext)
302 */
303 @Override
304 public synchronized CtfTmfEvent getNext(final ITmfContext context) {
305 if (fTrace == null) {
306 return null;
307 }
308 CtfTmfEvent event = null;
309 if (context instanceof CtfTmfContext) {
310 if (context.getLocation() == null || CtfLocation.INVALID_LOCATION.equals(context.getLocation().getLocationInfo())) {
311 return null;
312 }
313 CtfTmfContext ctfContext = (CtfTmfContext) context;
314 event = ctfContext.getCurrentEvent();
315
316 if (event != null) {
317 updateAttributes(context, event.getTimestamp());
318 ctfContext.advance();
319 ctfContext.increaseRank();
320 }
321 }
322
323 return event;
324 }
325
326 /**
327 * gets the CTFtrace that this is wrapping
328 *
329 * @return the CTF trace
330 */
331 public CTFTrace getCTFTrace() {
332 return fTrace;
333 }
334
335 /**
336 * Ctf traces have a clock with a unique uuid that will be used to identify
337 * the host. Traces with the same clock uuid will be known to have been made
338 * on the same machine.
339 *
340 * Note: uuid is an optional field, it may not be there for a clock.
341 */
342 @Override
343 public String getHostId() {
344 CTFClock clock = getCTFTrace().getClock();
345 if (clock != null) {
346 String clockHost = (String) clock.getProperty(CLOCK_HOST_PROPERTY);
347 if (clockHost != null) {
348 return clockHost;
349 }
350 }
351 return super.getHostId();
352 }
353
354 // -------------------------------------------
355 // ITmfTraceProperties
356 // -------------------------------------------
357
358 /**
359 * @since 2.0
360 */
361 @Override
362 public Map<String, String> getTraceProperties() {
363 Map<String, String> properties = new HashMap<>();
364 properties.putAll(fTrace.getEnvironment());
365 properties.put(Messages.CtfTmfTrace_HostID, getHostId());
366 return properties;
367 }
368
369 // -------------------------------------------
370 // Clocks
371 // -------------------------------------------
372
373 /**
374 * gets the clock offset
375 *
376 * @return the clock offset in ns
377 */
378 public long getOffset() {
379 if (fTrace != null) {
380 return fTrace.getOffset();
381 }
382 return 0;
383 }
384
385 /**
386 * Gets the list of declared events
387 *
388 * @since 3.0
389 */
390 @Override
391 public Set<ITmfEventType> getContainedEventTypes() {
392 TmfEventTypeManager instance = TmfEventTypeManager.getInstance();
393 Set<ITmfEventType> eventTypes = instance.getTypes(CtfTmfEventType.computeContextName(this));
394 return ImmutableSet.copyOf(eventTypes);
395 }
396
397 // -------------------------------------------
398 // Parser
399 // -------------------------------------------
400
401 @Override
402 public CtfTmfEvent parseEvent(ITmfContext context) {
403 CtfTmfEvent event = null;
404 if (context instanceof CtfTmfContext) {
405 final ITmfContext tmpContext = seekEvent(context.getLocation());
406 event = getNext(tmpContext);
407 }
408 return event;
409 }
410
411 /**
412 * Sets the cache size for a CtfTmfTrace.
413 */
414 protected void setCacheSize() {
415 setCacheSize(DEFAULT_CACHE_SIZE);
416 }
417
418 // -------------------------------------------
419 // Helpers
420 // -------------------------------------------
421
422 private static CtfIterator getIterator(CtfTmfTrace trace, CtfTmfContext context) {
423 return CtfIteratorManager.getIterator(trace, context);
424 }
425
426 /**
427 * Get an iterator to the trace
428 *
429 * @return an iterator to the trace
430 * @since 2.0
431 */
432 public CtfIterator createIterator() {
433 try {
434 return new CtfIterator(this);
435 } catch (CTFReaderException e) {
436 Activator.getDefault().logError(e.getMessage(), e);
437 }
438 return null;
439 }
440
441 // ------------------------------------------------------------------------
442 // Timestamp transformation functions
443 // ------------------------------------------------------------------------
444
445 /**
446 * @since 3.0
447 */
448 @Override
449 public CtfTmfTimestamp createTimestamp(long ts) {
450 return new CtfTmfTimestamp(getTimestampTransform().transform(ts));
451 }
452
453 private static int fCheckpointSize = -1;
454
455 /**
456 * @since 3.0
457 */
458 @Override
459 public synchronized int getCheckpointSize() {
460 if (fCheckpointSize == -1) {
461 TmfCheckpoint c = new TmfCheckpoint(new CtfTmfTimestamp(0), new CtfLocation(0, 0), 0);
462 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
463 b.clear();
464 c.serialize(b);
465 fCheckpointSize = b.position();
466 }
467
468 return fCheckpointSize;
469 }
470
471 @Override
472 protected ITmfTraceIndexer createIndexer(int interval) {
473 return new TmfBTreeTraceIndexer(this, interval);
474 }
475
476 /**
477 * @since 3.0
478 */
479 @Override
480 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
481 return new CtfLocation(bufferIn);
482 }
483
484 @Override
485 public boolean isComplete() {
486 if (getResource() == null) {
487 return true;
488 }
489
490 String host = null;
491 String port = null;
492 String sessionName = null;
493 try {
494 host = getResource().getPersistentProperty(CtfConstants.LIVE_HOST);
495 port = getResource().getPersistentProperty(CtfConstants.LIVE_PORT);
496 sessionName = getResource().getPersistentProperty(CtfConstants.LIVE_SESSION_NAME);
497 } catch (CoreException e) {
498 Activator.getDefault().logError(e.getMessage(), e);
499 // Something happened to the resource, assume we won't get any more data from it
500 return true;
501 }
502 return host == null || port == null || sessionName == null;
503 }
504
505 @Override
506 public void setComplete(final boolean isComplete) {
507 super.setComplete(isComplete);
508 try {
509 if (isComplete) {
510 getResource().setPersistentProperty(CtfConstants.LIVE_HOST, null);
511 getResource().setPersistentProperty(CtfConstants.LIVE_PORT, null);
512 getResource().setPersistentProperty(CtfConstants.LIVE_SESSION_NAME, null);
513 }
514 } catch (CoreException e) {
515 Activator.getDefault().logError(e.getMessage(), e);
516 }
517 }
518 }
This page took 0.042078 seconds and 5 git commands to generate.