ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ctf.core / src / org / eclipse / linuxtools / tmf / ctf / core / CtfTmfTrace.java
CommitLineData
b1baa808 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
b1baa808
MK
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 *
ea271da6
PT
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Updated for removal of context clone
e73a4ba5 12 * Geneviève Bastien - Added the createTimestamp function
b1baa808
MK
13 *******************************************************************************/
14
91e7f946 15package org.eclipse.linuxtools.tmf.ctf.core;
a3fc8213 16
96c0f2af 17import java.nio.BufferOverflowException;
032ecd45 18import java.nio.ByteBuffer;
409bea20 19import java.util.ArrayList;
2db2b43a 20import java.util.HashMap;
409bea20 21import java.util.List;
299e494e 22import java.util.Map;
409bea20 23import java.util.Set;
299e494e 24
a3fc8213
AM
25import org.eclipse.core.resources.IProject;
26import org.eclipse.core.resources.IResource;
6fd3c6e9 27import org.eclipse.core.runtime.CoreException;
a94410d9
MK
28import org.eclipse.core.runtime.IStatus;
29import org.eclipse.core.runtime.Status;
bb52f9bc 30import org.eclipse.linuxtools.ctf.core.event.CTFClock;
032ecd45 31import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
a3fc8213
AM
32import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
33import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
b5354daa 34import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
91e7f946 35import org.eclipse.linuxtools.internal.tmf.ctf.core.Activator;
6256d8ad 36import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
409bea20
GB
37import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
38import org.eclipse.linuxtools.tmf.core.event.ITmfEventType;
39import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
40import org.eclipse.linuxtools.tmf.core.event.TmfEventTypeManager;
b4f71e4a 41import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
3bd46eef
AM
42import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
43import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
a3fc8213 44import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
4b7c469f 45import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;
3480bf12 46import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
409bea20 47import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
4b7c469f 48import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
cd43d683 49import org.eclipse.linuxtools.tmf.core.trace.TraceValidationStatus;
032ecd45
MAL
50import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
51import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfTraceIndexer;
52import org.eclipse.linuxtools.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
53import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
54import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
a3db8436 55import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
a3fc8213 56
409bea20
GB
57import com.google.common.collect.ImmutableSet;
58
9ac2eb62 59/**
d09f973b
FC
60 * The CTf trace handler
61 *
62 * @version 1.0
63 * @author Matthew khouzam
9ac2eb62 64 */
22307af3 65public class CtfTmfTrace extends TmfTrace
090c006e 66 implements ITmfEventParser, ITmfTraceProperties, ITmfPersistentlyIndexable,
409bea20 67 ITmfTraceWithPreDefinedEvents, AutoCloseable {
a3fc8213 68
a94410d9
MK
69 // -------------------------------------------
70 // Constants
71 // -------------------------------------------
324a6a4a
BH
72 /**
73 * Default cache size for CTF traces
74 */
75 protected static final int DEFAULT_CACHE_SIZE = 50000;
64c2cb4c 76
bb52f9bc
GB
77 /*
78 * The Ctf clock unique identifier field
79 */
80 private static final String CLOCK_HOST_PROPERTY = "uuid"; //$NON-NLS-1$
cd43d683 81 private static final int CONFIDENCE = 10;
bb52f9bc 82
a94410d9
MK
83 // -------------------------------------------
84 // Fields
85 // -------------------------------------------
a3fc8213 86
4b7c469f
MK
87 /* Reference to the CTF Trace */
88 private CTFTrace fTrace;
a3fc8213 89
a94410d9
MK
90 // -------------------------------------------
91 // TmfTrace Overrides
92 // -------------------------------------------
b1baa808
MK
93 /**
94 * Method initTrace.
063f0d27
AM
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
b1baa808 102 * @throws TmfTraceException
07804639 103 * If something went wrong while reading the trace
b1baa808 104 */
a3fc8213 105 @Override
6256d8ad 106 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType)
b4f71e4a 107 throws TmfTraceException {
4a110860
AM
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();
324a6a4a 113
32c16b50
GB
114 super.initTrace(resource, path, eventType);
115
a3fc8213
AM
116 try {
117 this.fTrace = new CTFTrace(path);
53b235e1 118 CtfIteratorManager.addTrace(this);
81a2d02e 119 CtfTmfContext ctx;
99b483fe 120 /* Set the start and (current) end times for this trace */
81a2d02e 121 ctx = (CtfTmfContext) seekEvent(0L);
132a02b0 122 CtfTmfEvent event = getNext(ctx);
a94410d9 123 if ((ctx.getLocation().equals(CtfIterator.NULL_LOCATION)) || (ctx.getCurrentEvent() == null)) {
99b483fe
AM
124 /* Handle the case where the trace is empty */
125 this.setStartTime(TmfTimestamp.BIG_BANG);
126 } else {
132a02b0 127 final ITmfTimestamp curTime = event.getTimestamp();
21fb02fa
MK
128 this.setStartTime(curTime);
129 this.setEndTime(curTime);
99b483fe 130 }
409bea20
GB
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 }
25e48683 154 } catch (final CTFReaderException e) {
a3fc8213
AM
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 */
9fa32496 160 throw new TmfTraceException(e.getMessage(), e);
a3fc8213 161 }
a3fc8213
AM
162 }
163
090c006e
AM
164 @Override
165 public void close() {
166 dispose();
167 }
168
53b235e1
MK
169 @Override
170 public synchronized void dispose() {
171 CtfIteratorManager.removeTrace(this);
5d1c6919 172 if (fTrace != null) {
dd9752d5 173 fTrace.close();
5d1c6919
PT
174 fTrace = null;
175 }
53b235e1
MK
176 super.dispose();
177 }
178
b1baa808 179 /**
cd43d683
PT
180 * {@inheritDoc}
181 * <p>
182 * The default implementation sets the confidence to 10 if the trace is a
183 * valid CTF trace.
b1baa808 184 */
a3fc8213 185 @Override
a94410d9 186 public IStatus validate(final IProject project, final String path) {
dd9752d5
AM
187 IStatus status = new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
188 try (final CTFTrace temp = new CTFTrace(path);) {
07804639 189 if (!temp.majorIsSet()) {
dd9752d5 190 status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_MajorNotSet);
b5354daa 191 } else {
dd9752d5
AM
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 }
b5354daa 199 }
a94410d9 200 }
25e48683 201 } catch (final CTFReaderException e) {
dd9752d5
AM
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$
a3fc8213 205 }
96c0f2af 206
dd9752d5 207 return status;
a3fc8213
AM
208 }
209
b1baa808 210 /**
f474d36b 211 * Method getCurrentLocation. This is not applicable in CTF
a94410d9 212 *
f474d36b 213 * @return null, since the trace has no knowledge of the current location
b1baa808 214 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getCurrentLocation()
a3db8436 215 * @since 3.0
b1baa808 216 */
a3fc8213 217 @Override
1e1bef82 218 public ITmfLocation getCurrentLocation() {
f474d36b 219 return null;
a3fc8213
AM
220 }
221
a3db8436
AM
222 /**
223 * @since 3.0
224 */
a3fc8213 225 @Override
1e1bef82 226 public double getLocationRatio(ITmfLocation location) {
4b7c469f 227 final CtfLocation curLocation = (CtfLocation) location;
81a2d02e 228 final CtfTmfContext context = new CtfTmfContext(this);
53b235e1 229 context.setLocation(curLocation);
5976d44a 230 context.seek(curLocation.getLocationInfo());
a94410d9 231 final CtfLocationInfo currentTime = ((CtfLocationInfo) context.getLocation().getLocationInfo());
53b235e1
MK
232 final long startTime = getIterator(this, context).getStartTime();
233 final long endTime = getIterator(this, context).getEndTime();
132a02b0 234 return ((double) currentTime.getTimestamp() - startTime)
53b235e1 235 / (endTime - startTime);
a3fc8213
AM
236 }
237
b1baa808
MK
238 /**
239 * Method seekEvent.
a94410d9
MK
240 *
241 * @param location
242 * ITmfLocation<?>
b1baa808 243 * @return ITmfContext
a3db8436 244 * @since 3.0
b1baa808 245 */
a3fc8213 246 @Override
76643eb7 247 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
ce2388e0 248 CtfLocation currentLocation = (CtfLocation) location;
81a2d02e 249 CtfTmfContext context = new CtfTmfContext(this);
76643eb7
BH
250 if (fTrace == null) {
251 context.setLocation(null);
252 context.setRank(ITmfContext.UNKNOWN_RANK);
253 return context;
254 }
4a110860
AM
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 */
11d6f468 260 if (currentLocation == null) {
f5df94f8 261 currentLocation = new CtfLocation(new CtfLocationInfo(0L, 0L));
4a110860 262 context.setRank(0);
11d6f468 263 }
5976d44a 264 if (currentLocation.getLocationInfo() == CtfLocation.INVALID_LOCATION) {
962fb72f 265 currentLocation = new CtfLocation(getCTFTrace().getCurrentEndTime() + 1, 0L);
1191a574 266 }
f474d36b 267 context.setLocation(currentLocation);
7f0bab07 268 if (location == null) {
962fb72f
PT
269 long timestamp = getIterator(this, context).getCurrentTimestamp();
270 currentLocation = new CtfLocation(timestamp, 0);
7f0bab07 271 }
a94410d9 272 if (context.getRank() != 0) {
3bd44ac8 273 context.setRank(ITmfContext.UNKNOWN_RANK);
64c2cb4c 274 }
f474d36b 275 return context;
a3fc8213
AM
276 }
277
a3fc8213 278 @Override
76643eb7 279 public synchronized ITmfContext seekEvent(double ratio) {
81a2d02e 280 CtfTmfContext context = new CtfTmfContext(this);
76643eb7
BH
281 if (fTrace == null) {
282 context.setLocation(null);
283 context.setRank(ITmfContext.UNKNOWN_RANK);
284 return context;
285 }
962fb72f
PT
286 final long end = getCTFTrace().getCurrentEndTime();
287 final long start = getCTFTrace().getCurrentStartTime();
b2dc9e02 288 final long diff = end - start;
15e89960 289 final long ratioTs = Math.round(diff * ratio) + start;
b2dc9e02 290 context.seek(ratioTs);
f474d36b
PT
291 context.setRank(ITmfContext.UNKNOWN_RANK);
292 return context;
a3fc8213
AM
293 }
294
b1baa808
MK
295 /**
296 * Method readNextEvent.
a94410d9
MK
297 *
298 * @param context
299 * ITmfContext
b1baa808 300 * @return CtfTmfEvent
c32744d6 301 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNext(ITmfContext)
b1baa808 302 */
a3fc8213 303 @Override
4b7c469f 304 public synchronized CtfTmfEvent getNext(final ITmfContext context) {
faa38350
PT
305 if (fTrace == null) {
306 return null;
307 }
f474d36b 308 CtfTmfEvent event = null;
81a2d02e 309 if (context instanceof CtfTmfContext) {
575beffc 310 if (context.getLocation() == null || CtfLocation.INVALID_LOCATION.equals(context.getLocation().getLocationInfo())) {
ae09313d
PT
311 return null;
312 }
81a2d02e 313 CtfTmfContext ctfContext = (CtfTmfContext) context;
788ddcbc 314 event = ctfContext.getCurrentEvent();
4a110860 315
324a6a4a
BH
316 if (event != null) {
317 updateAttributes(context, event.getTimestamp());
788ddcbc
MK
318 ctfContext.advance();
319 ctfContext.increaseRank();
324a6a4a 320 }
f474d36b 321 }
4a110860 322
aa572e22 323 return event;
a3fc8213
AM
324 }
325
4b7c469f
MK
326 /**
327 * gets the CTFtrace that this is wrapping
a94410d9 328 *
4b7c469f
MK
329 * @return the CTF trace
330 */
331 public CTFTrace getCTFTrace() {
a3fc8213
AM
332 return fTrace;
333 }
a1a24d68 334
bb52f9bc
GB
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
a94410d9 354 // -------------------------------------------
22307af3 355 // ITmfTraceProperties
a94410d9 356 // -------------------------------------------
4b7c469f
MK
357
358 /**
299e494e 359 * @since 2.0
4b7c469f 360 */
22307af3
AM
361 @Override
362 public Map<String, String> getTraceProperties() {
2db2b43a
GB
363 Map<String, String> properties = new HashMap<>();
364 properties.putAll(fTrace.getEnvironment());
365 properties.put(Messages.CtfTmfTrace_HostID, getHostId());
366 return properties;
4b7c469f
MK
367 }
368
a94410d9
MK
369 // -------------------------------------------
370 // Clocks
371 // -------------------------------------------
bfe038ff 372
9ac2eb62
MK
373 /**
374 * gets the clock offset
a94410d9 375 *
9ac2eb62
MK
376 * @return the clock offset in ns
377 */
a94410d9
MK
378 public long getOffset() {
379 if (fTrace != null) {
bfe038ff
MK
380 return fTrace.getOffset();
381 }
382 return 0;
383 }
384
3480bf12 385 /**
409bea20 386 * Gets the list of declared events
3480bf12 387 *
409bea20 388 * @since 3.0
3480bf12 389 */
409bea20
GB
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);
3480bf12
GB
395 }
396
a94410d9
MK
397 // -------------------------------------------
398 // Parser
399 // -------------------------------------------
4b7c469f
MK
400
401 @Override
bfe038ff 402 public CtfTmfEvent parseEvent(ITmfContext context) {
4b7c469f 403 CtfTmfEvent event = null;
ea271da6
PT
404 if (context instanceof CtfTmfContext) {
405 final ITmfContext tmpContext = seekEvent(context.getLocation());
406 event = getNext(tmpContext);
4b7c469f
MK
407 }
408 return event;
11d6f468 409 }
64c2cb4c 410
324a6a4a 411 /**
64c2cb4c 412 * Sets the cache size for a CtfTmfTrace.
324a6a4a
BH
413 */
414 protected void setCacheSize() {
415 setCacheSize(DEFAULT_CACHE_SIZE);
416 }
ce2388e0 417
a94410d9
MK
418 // -------------------------------------------
419 // Helpers
420 // -------------------------------------------
53b235e1 421
a94410d9 422 private static CtfIterator getIterator(CtfTmfTrace trace, CtfTmfContext context) {
53b235e1
MK
423 return CtfIteratorManager.getIterator(trace, context);
424 }
36dd544c
MK
425
426 /**
427 * Get an iterator to the trace
428 *
429 * @return an iterator to the trace
ed59ab27 430 * @since 2.0
36dd544c 431 */
a94410d9 432 public CtfIterator createIterator() {
db8e8f7d
AM
433 try {
434 return new CtfIterator(this);
435 } catch (CTFReaderException e) {
91e7f946 436 Activator.getDefault().logError(e.getMessage(), e);
db8e8f7d
AM
437 }
438 return null;
36dd544c 439 }
e73a4ba5
GB
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 }
032ecd45
MAL
452
453 private static int fCheckpointSize = -1;
454
c4767854
AM
455 /**
456 * @since 3.0
457 */
032ecd45
MAL
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
c4767854
AM
476 /**
477 * @since 3.0
478 */
032ecd45
MAL
479 @Override
480 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
481 return new CtfLocation(bufferIn);
482 }
6fd3c6e9
MAL
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 }
a3fc8213 518}
This page took 0.085844 seconds and 5 git commands to generate.