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