ctf: java 8 compliance of javadoc
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFTrace.java
CommitLineData
866e5b51 1/*******************************************************************************
fe75d403 2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
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 *
4311ac8b
MAL
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Alexandre Montplaisir - Initial API and implementation
890f9136 12 * Simon Delisle - Replace LinkedList by TreeSet in callsitesByName attribute
866e5b51
FC
13 *******************************************************************************/
14
15package org.eclipse.linuxtools.ctf.core.trace;
16
17import java.io.File;
18import java.io.FileFilter;
19import java.io.FileInputStream;
20import java.io.IOException;
debcffff 21import java.io.Serializable;
866e5b51
FC
22import java.nio.ByteOrder;
23import java.nio.MappedByteBuffer;
24import java.nio.channels.FileChannel;
25import java.nio.channels.FileChannel.MapMode;
26import java.util.Arrays;
a95fddf5 27import java.util.Collections;
866e5b51
FC
28import java.util.Comparator;
29import java.util.HashMap;
aa572e22 30import java.util.Iterator;
d0d3aa1b
AM
31import java.util.LinkedList;
32import java.util.List;
866e5b51 33import java.util.Map;
aa572e22 34import java.util.Map.Entry;
866e5b51 35import java.util.Set;
4c9d2941 36import java.util.TreeSet;
866e5b51
FC
37import java.util.UUID;
38
4c9d2941 39import org.eclipse.linuxtools.ctf.core.event.CTFCallsite;
866e5b51 40import org.eclipse.linuxtools.ctf.core.event.CTFClock;
788ddcbc 41import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
8e964be1 42import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
486efb2e 43import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
866e5b51
FC
44import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
45import org.eclipse.linuxtools.ctf.core.event.types.Definition;
46import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
47import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
48import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
49import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
890f9136 50import org.eclipse.linuxtools.internal.ctf.core.event.CTFCallsiteComparator;
ce2388e0 51import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
866e5b51
FC
52
53/**
d37aaa7f
FC
54 * A CTF trace on the file system.
55 *
866e5b51
FC
56 * Represents a trace on the filesystem. It is responsible of parsing the
57 * metadata, creating declarations data structures, indexing the event packets
58 * (in other words, all the work that can be shared between readers), but the
59 * actual reading of events is left to TraceReader.
debcffff 60 *
866e5b51
FC
61 * @author Matthew Khouzam
62 * @version $Revision: 1.0 $
63 */
dd9752d5 64public class CTFTrace implements IDefinitionScope, AutoCloseable {
866e5b51 65
866e5b51
FC
66 @SuppressWarnings("nls")
67 @Override
68 public String toString() {
69 /* Only for debugging, shouldn't be externalized */
fe75d403
MK
70 return "CTFTrace [path=" + fPath + ", major=" + fMajor + ", minor="
71 + fMinor + ", uuid=" + fUuid + "]";
866e5b51
FC
72 }
73
74 /**
75 * The trace directory on the filesystem.
76 */
fe75d403 77 private final File fPath;
866e5b51 78
866e5b51
FC
79 /**
80 * Major CTF version number
81 */
fe75d403 82 private Long fMajor;
866e5b51
FC
83
84 /**
85 * Minor CTF version number
86 */
fe75d403 87 private Long fMinor;
866e5b51
FC
88
89 /**
90 * Trace UUID
91 */
fe75d403 92 private UUID fUuid;
866e5b51
FC
93
94 /**
95 * Trace byte order
96 */
fe75d403 97 private ByteOrder fByteOrder;
866e5b51
FC
98
99 /**
100 * Packet header structure declaration
101 */
fe75d403 102 private StructDeclaration fPacketHeaderDecl = null;
866e5b51 103
1d7277f3
MK
104 /**
105 * The clock of the trace
106 */
fe75d403 107 private CTFClock fSingleClock;
1d7277f3 108
866e5b51
FC
109 /**
110 * Packet header structure definition
debcffff 111 *
866e5b51
FC
112 * This is only used when opening the trace files, to read the first packet
113 * header and see if they are valid trace files.
114 */
fe75d403 115 private StructDefinition fPacketHeaderDef;
866e5b51
FC
116
117 /**
118 * Collection of streams contained in the trace.
119 */
fe75d403 120 private final Map<Long, Stream> fStreams = new HashMap<>();
866e5b51
FC
121
122 /**
123 * Collection of environment variables set by the tracer
124 */
fe75d403 125 private final Map<String, String> fEnvironment = new HashMap<>();
866e5b51
FC
126
127 /**
128 * Collection of all the clocks in a system.
129 */
fe75d403 130 private final Map<String, CTFClock> fClocks = new HashMap<>();
866e5b51 131
5d1c6919 132 /** FileInputStreams to the streams */
fe75d403 133 private final List<FileInputStream> fFileInputStreams = new LinkedList<>();
26ea03d2 134
c88e827d 135 /** Handlers for the metadata files */
0594c61c
AM
136 private static final FileFilter METADATA_FILE_FILTER = new MetadataFileFilter();
137 private static final Comparator<File> METADATA_COMPARATOR = new MetadataComparator();
866e5b51 138
4c9d2941 139 /** Callsite helpers */
fe75d403 140 private CTFCallsiteComparator fCtfCallsiteComparator = new CTFCallsiteComparator();
890f9136 141
fe75d403 142 private Map<String, TreeSet<CTFCallsite>> fCallsitesByName = new HashMap<>();
0594c61c 143
4c9d2941 144 /** Callsite helpers */
fe75d403 145 private TreeSet<CTFCallsite> fCallsitesByIP = new TreeSet<>();
788ddcbc 146
866e5b51
FC
147 // ------------------------------------------------------------------------
148 // Constructors
149 // ------------------------------------------------------------------------
150
151 /**
152 * Trace constructor.
debcffff 153 *
866e5b51 154 * @param path
be6df2d8
AM
155 * Filesystem path of the trace directory
156 * @throws CTFReaderException
157 * If no CTF trace was found at the path
866e5b51
FC
158 */
159 public CTFTrace(String path) throws CTFReaderException {
160 this(new File(path));
aa572e22 161
866e5b51
FC
162 }
163
164 /**
165 * Trace constructor.
debcffff 166 *
866e5b51
FC
167 * @param path
168 * Filesystem path of the trace directory.
169 * @throws CTFReaderException
be6df2d8 170 * If no CTF trace was found at the path
866e5b51 171 */
866e5b51 172 public CTFTrace(File path) throws CTFReaderException {
fe75d403 173 fPath = path;
0594c61c 174 final Metadata metadata = new Metadata(this);
866e5b51 175
c88e827d 176 /* Set up the internal containers for this trace */
fe75d403 177 if (!fPath.exists()) {
8a95ce5a
BH
178 throw new CTFReaderException("Trace (" + path.getPath() + ") doesn't exist. Deleted or moved?"); //$NON-NLS-1$ //$NON-NLS-2$
179 }
d0d3aa1b 180
fe75d403 181 if (!fPath.isDirectory()) {
d0d3aa1b
AM
182 throw new CTFReaderException("Path must be a valid directory"); //$NON-NLS-1$
183 }
c88e827d
AM
184
185 /* Open and parse the metadata file */
58129ff7 186 metadata.parseFile();
c88e827d 187
58129ff7
MK
188 init(path);
189 }
190
191 /**
192 * Streamed constructor
fe75d403 193 *
58129ff7
MK
194 * @since 3.0
195 */
196 public CTFTrace() {
fe75d403 197 fPath = null;
58129ff7
MK
198 init();
199 }
200
201 private void init() {
c88e827d 202 /* Create the definitions needed to read things from the files */
fe75d403
MK
203 if (fPacketHeaderDecl != null) {
204 fPacketHeaderDef = fPacketHeaderDecl.createDefinition(this, "packet.header"); //$NON-NLS-1$
c88e827d 205 }
58129ff7
MK
206 }
207
208 private void init(File path) throws CTFReaderException {
209
210 init();
211
212 /* Open all the trace files */
c88e827d
AM
213
214 /* List files not called metadata and not hidden. */
0594c61c
AM
215 File[] files = path.listFiles(METADATA_FILE_FILTER);
216 Arrays.sort(files, METADATA_COMPARATOR);
fe75d403 217
c88e827d 218 /* Try to open each file */
d0d3aa1b
AM
219 for (File streamFile : files) {
220 openStreamInput(streamFile);
c88e827d 221 }
788ddcbc 222
c88e827d 223 /* Create their index */
f7c5789a
EB
224 for (Stream stream : getStreams()) {
225 Set<StreamInput> inputs = stream.getStreamInputs();
c88e827d 226 for (StreamInput s : inputs) {
fe75d403 227 addStream(s);
c88e827d
AM
228 }
229 }
866e5b51
FC
230 }
231
5d1c6919
PT
232 /**
233 * Dispose the trace
a7297cd3 234 *
dd9752d5 235 * @since 3.0
5d1c6919 236 */
dd9752d5
AM
237 @Override
238 public void close() {
fe75d403 239 for (FileInputStream fis : fFileInputStreams) {
5d1c6919 240 if (fis != null) {
26ea03d2 241 try {
5d1c6919 242 fis.close();
26ea03d2 243 } catch (IOException e) {
aa572e22 244 // do nothing it's ok, we tried to close it.
26ea03d2
AM
245 }
246 }
247 }
248 }
249
866e5b51
FC
250 // ------------------------------------------------------------------------
251 // Getters/Setters/Predicates
252 // ------------------------------------------------------------------------
253
aa572e22 254 /**
be6df2d8
AM
255 * Gets an event declaration hash map for a given streamID
256 *
257 * @param streamId
258 * The ID of the stream from which to read
259 * @return The Hash map with the event declarations
0594c61c 260 * @since 2.0
788ddcbc 261 */
0594c61c 262 public Map<Long, IEventDeclaration> getEvents(Long streamId) {
fe75d403 263 return fStreams.get(streamId).getEvents();
788ddcbc
MK
264 }
265
aa572e22 266 /**
788ddcbc 267 * Gets an event Declaration hashmap for a given StreamInput
7ff6d3cf
MK
268 *
269 * @param id
270 * the StreamInput
271 * @return an empty hashmap, please see deprecated
e6809677 272 * @since 2.0
a7297cd3
SD
273 * @deprecated You should be using
274 * {@link StreamInputReader#getEventDefinitions()} instead.
788ddcbc 275 */
7ff6d3cf 276 @Deprecated
0594c61c 277 public Map<Long, EventDefinition> getEventDefs(StreamInput id) {
3de23137 278 return new HashMap<>();
788ddcbc
MK
279 }
280
281 /**
282 * Get an event by it's ID
aa572e22 283 *
be6df2d8
AM
284 * @param streamId
285 * The ID of the stream from which to read
788ddcbc
MK
286 * @param id
287 * the ID of the event
288 * @return the event declaration
8e964be1 289 * @since 2.0
aa572e22 290 */
8e964be1 291 public IEventDeclaration getEventType(long streamId, long id) {
788ddcbc 292 return getEvents(streamId).get(id);
aa572e22
MK
293 }
294
866e5b51
FC
295 /**
296 * Method getStream gets the stream for a given id
debcffff 297 *
866e5b51
FC
298 * @param id
299 * Long the id of the stream
300 * @return Stream the stream that we need
e6809677 301 * @since 2.0
866e5b51
FC
302 */
303 public Stream getStream(Long id) {
fe75d403 304 return fStreams.get(id);
866e5b51
FC
305 }
306
307 /**
308 * Method nbStreams gets the number of available streams
debcffff 309 *
866e5b51
FC
310 * @return int the number of streams
311 */
312 public int nbStreams() {
fe75d403 313 return fStreams.size();
866e5b51
FC
314 }
315
316 /**
317 * Method setMajor sets the major version of the trace (DO NOT USE)
debcffff 318 *
866e5b51
FC
319 * @param major
320 * long the major version
321 */
322 public void setMajor(long major) {
fe75d403 323 fMajor = major;
866e5b51
FC
324 }
325
326 /**
327 * Method setMinor sets the minor version of the trace (DO NOT USE)
debcffff 328 *
866e5b51
FC
329 * @param minor
330 * long the minor version
331 */
332 public void setMinor(long minor) {
fe75d403 333 fMinor = minor;
866e5b51
FC
334 }
335
336 /**
337 * Method setUUID sets the UUID of a trace
debcffff 338 *
866e5b51
FC
339 * @param uuid
340 * UUID
341 */
342 public void setUUID(UUID uuid) {
fe75d403 343 fUuid = uuid;
866e5b51
FC
344 }
345
346 /**
347 * Method setByteOrder sets the byte order
debcffff 348 *
866e5b51
FC
349 * @param byteOrder
350 * ByteOrder of the trace, can be little-endian or big-endian
351 */
352 public void setByteOrder(ByteOrder byteOrder) {
fe75d403 353 fByteOrder = byteOrder;
866e5b51
FC
354 }
355
356 /**
357 * Method setPacketHeader sets the packet header of a trace (DO NOT USE)
debcffff 358 *
866e5b51
FC
359 * @param packetHeader
360 * StructDeclaration the header in structdeclaration form
361 */
362 public void setPacketHeader(StructDeclaration packetHeader) {
fe75d403 363 fPacketHeaderDecl = packetHeader;
866e5b51
FC
364 }
365
366 /**
07804639 367 * Method majorIsSet is the major version number set?
debcffff 368 *
866e5b51 369 * @return boolean is the major set?
c4767854 370 * @since 3.0
866e5b51 371 */
07804639 372 public boolean majorIsSet() {
fe75d403 373 return fMajor != null;
866e5b51
FC
374 }
375
376 /**
377 * Method minorIsSet. is the minor version number set?
debcffff 378 *
866e5b51
FC
379 * @return boolean is the minor set?
380 */
381 public boolean minorIsSet() {
fe75d403 382 return fMinor != null;
866e5b51
FC
383 }
384
385 /**
386 * Method UUIDIsSet is the UUID set?
debcffff 387 *
866e5b51 388 * @return boolean is the UUID set?
0594c61c 389 * @since 2.0
866e5b51 390 */
0594c61c 391 public boolean uuidIsSet() {
fe75d403 392 return fUuid != null;
866e5b51
FC
393 }
394
395 /**
396 * Method byteOrderIsSet is the byteorder set?
debcffff 397 *
866e5b51
FC
398 * @return boolean is the byteorder set?
399 */
400 public boolean byteOrderIsSet() {
fe75d403 401 return fByteOrder != null;
866e5b51
FC
402 }
403
404 /**
405 * Method packetHeaderIsSet is the packet header set?
debcffff 406 *
866e5b51
FC
407 * @return boolean is the packet header set?
408 */
409 public boolean packetHeaderIsSet() {
fe75d403 410 return fPacketHeaderDecl != null;
866e5b51
FC
411 }
412
413 /**
414 * Method getUUID gets the trace UUID
debcffff 415 *
866e5b51
FC
416 * @return UUID gets the trace UUID
417 */
418 public UUID getUUID() {
fe75d403 419 return fUuid;
866e5b51
FC
420 }
421
422 /**
423 * Method getMajor gets the trace major version
debcffff 424 *
866e5b51
FC
425 * @return long gets the trace major version
426 */
427 public long getMajor() {
fe75d403 428 return fMajor;
866e5b51
FC
429 }
430
431 /**
432 * Method getMinor gets the trace minor version
debcffff 433 *
866e5b51
FC
434 * @return long gets the trace minor version
435 */
436 public long getMinor() {
fe75d403 437 return fMinor;
866e5b51
FC
438 }
439
440 /**
441 * Method getByteOrder gets the trace byte order
debcffff 442 *
866e5b51
FC
443 * @return ByteOrder gets the trace byte order
444 */
0594c61c 445 public final ByteOrder getByteOrder() {
fe75d403 446 return fByteOrder;
866e5b51
FC
447 }
448
449 /**
450 * Method getPacketHeader gets the trace packet header
debcffff 451 *
866e5b51
FC
452 * @return StructDeclaration gets the trace packet header
453 */
454 public StructDeclaration getPacketHeader() {
fe75d403 455 return fPacketHeaderDecl;
866e5b51
FC
456 }
457
458 /**
459 * Method getTraceDirectory gets the trace directory
debcffff 460 *
866e5b51
FC
461 * @return File the path in "File" format.
462 */
463 public File getTraceDirectory() {
fe75d403 464 return fPath;
866e5b51
FC
465 }
466
467 /**
f7c5789a 468 * Get all the streams as an iterable.
debcffff 469 *
ab04fc6b 470 * @return Iterable&lt;Stream&gt; an iterable over streams.
951bb9d9 471 * @since 3.0
866e5b51 472 */
f7c5789a 473 public Iterable<Stream> getStreams() {
fe75d403 474 return fStreams.values();
866e5b51
FC
475 }
476
477 /**
478 * Method getPath gets the path of the trace directory
debcffff 479 *
866e5b51
FC
480 * @return String the path of the trace directory, in string format.
481 * @see java.io.File#getPath()
482 */
483 @Override
484 public String getPath() {
fe75d403 485 return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$
866e5b51
FC
486 }
487
488 // ------------------------------------------------------------------------
489 // Operations
490 // ------------------------------------------------------------------------
491
fe75d403
MK
492 private void addStream(StreamInput s) {
493
494 /*
495 * Copy the events
496 */
497 Iterator<Entry<Long, IEventDeclaration>> it = s.getStream()
498 .getEvents().entrySet().iterator();
499 while (it.hasNext()) {
500 Entry<Long, IEventDeclaration> pairs = it.next();
501 Long eventNum = pairs.getKey();
502 IEventDeclaration eventDec = pairs.getValue();
503 getEvents(s.getStream().getId()).put(eventNum, eventDec);
504 }
505
506 /*
507 * index the trace
508 */
509 s.setupIndex();
510 }
511
866e5b51
FC
512 /**
513 * Tries to open the given file, reads the first packet header of the file
fe75d403 514 * and check its validity. This will add a file to a stream as a streaminput
debcffff 515 *
866e5b51
FC
516 * @param streamFile
517 * A trace file in the trace directory.
26ea03d2
AM
518 * @param index
519 * Which index in the class' streamFileChannel array this file
520 * must use
866e5b51 521 * @throws CTFReaderException
fe75d403 522 * if there is a file error
866e5b51 523 */
fe75d403 524 private Stream openStreamInput(File streamFile) throws CTFReaderException {
866e5b51
FC
525 MappedByteBuffer byteBuffer;
526 BitBuffer streamBitBuffer;
d0d3aa1b
AM
527 Stream stream;
528 FileChannel fc;
866e5b51
FC
529
530 if (!streamFile.canRead()) {
531 throw new CTFReaderException("Unreadable file : " //$NON-NLS-1$
532 + streamFile.getPath());
533 }
534
fe75d403 535 FileInputStream fis = null;
866e5b51
FC
536 try {
537 /* Open the file and get the FileChannel */
fe75d403
MK
538 fis = new FileInputStream(streamFile);
539 fFileInputStreams.add(fis);
5d1c6919 540 fc = fis.getChannel();
866e5b51
FC
541
542 /* Map one memory page of 4 kiB */
92bdd7d4 543 byteBuffer = fc.map(MapMode.READ_ONLY, 0, (int) Math.min(fc.size(), 4096L));
866e5b51 544 } catch (IOException e) {
fe75d403
MK
545 if (fis != null) {
546 fFileInputStreams.remove(fis);
547 }
866e5b51 548 /* Shouldn't happen at this stage if every other check passed */
0594c61c 549 throw new CTFReaderException(e);
866e5b51
FC
550 }
551
552 /* Create a BitBuffer with this mapping and the trace byte order */
553 streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
554
fe75d403 555 if (fPacketHeaderDef != null) {
866e5b51 556 /* Read the packet header */
fe75d403 557 fPacketHeaderDef.read(streamBitBuffer);
866e5b51
FC
558
559 /* Check the magic number */
fe75d403 560 IntegerDefinition magicDef = (IntegerDefinition) fPacketHeaderDef
aa572e22 561 .lookupDefinition("magic"); //$NON-NLS-1$
866e5b51
FC
562 int magic = (int) magicDef.getValue();
563 if (magic != Utils.CTF_MAGIC) {
564 throw new CTFReaderException("CTF magic mismatch"); //$NON-NLS-1$
565 }
566
567 /* Check UUID */
fe75d403 568 ArrayDefinition uuidDef = (ArrayDefinition) fPacketHeaderDef
aa572e22 569 .lookupDefinition("uuid"); //$NON-NLS-1$
866e5b51
FC
570 if (uuidDef != null) {
571 byte[] uuidArray = new byte[Utils.UUID_LEN];
572
573 for (int i = 0; i < Utils.UUID_LEN; i++) {
aa572e22
MK
574 IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
575 .getElem(i);
866e5b51
FC
576 uuidArray[i] = (byte) uuidByteDef.getValue();
577 }
578
579 UUID otheruuid = Utils.makeUUID(uuidArray);
580
fe75d403 581 if (!fUuid.equals(otheruuid)) {
866e5b51
FC
582 throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
583 }
584 }
585
1fbaecd1 586 /* Read the stream ID */
fe75d403 587 Definition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
1fbaecd1 588
a7297cd3
SD
589 if (streamIDDef instanceof IntegerDefinition) { // this doubles as a
590 // null check
1fbaecd1 591 long streamID = ((IntegerDefinition) streamIDDef).getValue();
fe75d403 592 stream = fStreams.get(streamID);
1fbaecd1
AM
593 } else {
594 /* No stream_id in the packet header */
fe75d403 595 stream = fStreams.get(null);
1fbaecd1
AM
596 }
597
866e5b51
FC
598 } else {
599 /* No packet header, we suppose there is only one stream */
fe75d403 600 stream = fStreams.get(null);
d0d3aa1b 601 }
866e5b51 602
4311ac8b
MAL
603 if (stream == null) {
604 throw new CTFReaderException("Unexpected end of stream"); //$NON-NLS-1$
605 }
606
d0d3aa1b
AM
607 /* Create the stream input */
608 StreamInput streamInput = new StreamInput(stream, fc, streamFile);
866e5b51 609
d0d3aa1b
AM
610 /* Add a reference to the streamInput in the stream */
611 stream.addInput(streamInput);
fe75d403
MK
612
613 return stream;
866e5b51
FC
614 }
615
616 /**
617 * Looks up a definition from packet
debcffff 618 *
866e5b51
FC
619 * @param lookupPath
620 * String
621 * @return Definition
622 * @see org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope#lookupDefinition(String)
623 */
624 @Override
625 public Definition lookupDefinition(String lookupPath) {
626 if (lookupPath.equals("trace.packet.header")) { //$NON-NLS-1$
fe75d403 627 return fPacketHeaderDef;
866e5b51
FC
628 }
629 return null;
630 }
631
632 /**
fe75d403
MK
633 * Add a new stream file to support new streams while the trace is being
634 * read.
635 *
636 * @param streamFile
637 * the file of the stream
638 * @throws CTFReaderException
639 * A stream had an issue being read
fe75d403
MK
640 * @since 3.0
641 */
642 public void addStreamFile(File streamFile) throws CTFReaderException {
643 openStreamInput(streamFile);
644 }
645
646 /**
647 * Registers a new stream to the trace.
debcffff 648 *
866e5b51
FC
649 * @param stream
650 * A stream object.
866e5b51 651 * @throws ParseException
be6df2d8 652 * If there was some problem reading the metadata
e6809677 653 * @since 2.0
866e5b51
FC
654 */
655 public void addStream(Stream stream) throws ParseException {
656
fe75d403
MK
657 /*
658 * Init if not done before
659 */
660 init();
661
866e5b51
FC
662 /*
663 * If there is already a stream without id (the null key), it must be
664 * the only one
665 */
fe75d403 666 if (fStreams.get(null) != null) {
866e5b51
FC
667 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
668 }
669
670 /*
1d7277f3
MK
671 * If the stream we try to add has the null key, it must be the only
672 * one. Thus, if the streams container is not empty, it is not valid.
866e5b51 673 */
fe75d403 674 if ((stream.getId() == null) && (fStreams.size() != 0)) {
866e5b51
FC
675 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
676 }
677
fe75d403
MK
678 /*
679 * If a stream with the same ID already exists, it is not valid.
680 */
681 Stream existingStream = fStreams.get(stream.getId());
682 if (existingStream != null) {
866e5b51
FC
683 throw new ParseException("Stream id already exists"); //$NON-NLS-1$
684 }
685
29a7d6ee 686 /* This stream is valid and has a unique id. */
fe75d403 687 fStreams.put(stream.getId(), stream);
866e5b51
FC
688 }
689
9ac2eb62 690 /**
29a7d6ee 691 * Gets the Environment variables from the trace metadata (See CTF spec)
a7297cd3 692 *
a95fddf5
EB
693 * @return The environment variables in the form of an unmodifiable map
694 * (key, value)
486efb2e 695 * @since 2.0
9ac2eb62 696 */
791072b0 697 public Map<String, String> getEnvironment() {
fe75d403 698 return Collections.unmodifiableMap(fEnvironment);
866e5b51
FC
699 }
700
9ac2eb62
MK
701 /**
702 * Add a variable to the environment variables
a7297cd3
SD
703 *
704 * @param varName
705 * the name of the variable
706 * @param varValue
707 * the value of the variable
9ac2eb62 708 */
c88e827d 709 public void addEnvironmentVar(String varName, String varValue) {
fe75d403 710 fEnvironment.put(varName, varValue);
866e5b51
FC
711 }
712
9ac2eb62
MK
713 /**
714 * Add a clock to the clock list
a7297cd3
SD
715 *
716 * @param nameValue
717 * the name of the clock (full name with scope)
718 * @param ctfClock
719 * the clock
9ac2eb62 720 */
866e5b51 721 public void addClock(String nameValue, CTFClock ctfClock) {
fe75d403 722 fClocks.put(nameValue, ctfClock);
866e5b51
FC
723 }
724
9ac2eb62
MK
725 /**
726 * gets the clock with a specific name
a7297cd3
SD
727 *
728 * @param name
729 * the name of the clock.
9ac2eb62
MK
730 * @return the clock
731 */
c88e827d 732 public CTFClock getClock(String name) {
fe75d403 733 return fClocks.get(name);
866e5b51
FC
734 }
735
9ac2eb62 736 /**
1d7277f3
MK
737 * gets the clock if there is only one. (this is 100% of the use cases as of
738 * June 2012)
739 *
9ac2eb62
MK
740 * @return the clock
741 */
8ecc80f3 742 public final CTFClock getClock() {
fe75d403
MK
743 if (fClocks.size() == 1) {
744 fSingleClock = fClocks.get(fClocks.keySet().iterator().next());
745 return fSingleClock;
866e5b51
FC
746 }
747 return null;
748 }
749
9ac2eb62
MK
750 /**
751 * gets the time offset of a clock with respect to UTC in nanoseconds
1d7277f3 752 *
9ac2eb62
MK
753 * @return the time offset of a clock with respect to UTC in nanoseconds
754 */
8ecc80f3 755 public final long getOffset() {
c88e827d 756 if (getClock() == null) {
ce2388e0
FC
757 return 0;
758 }
fe75d403 759 return fSingleClock.getClockOffset();
1d7277f3
MK
760 }
761
762 /**
763 * gets the time offset of a clock with respect to UTC in nanoseconds
764 *
765 * @return the time offset of a clock with respect to UTC in nanoseconds
766 */
0594c61c 767 private double getTimeScale() {
1d7277f3
MK
768 if (getClock() == null) {
769 return 1.0;
770 }
fe75d403 771 return fSingleClock.getClockScale();
1d7277f3
MK
772 }
773
774 /**
775 * Does the trace need to time scale?
776 *
777 * @return if the trace is in ns or cycles.
778 */
0594c61c 779 private boolean clockNeedsScale() {
1d7277f3
MK
780 if (getClock() == null) {
781 return false;
782 }
fe75d403 783 return fSingleClock.isClockScaled();
1d7277f3
MK
784 }
785
786 /**
787 * the inverse clock for returning to a scale.
788 *
789 * @return 1.0 / scale
790 */
0594c61c 791 private double getInverseTimeScale() {
1d7277f3
MK
792 if (getClock() == null) {
793 return 1.0;
794 }
fe75d403 795 return fSingleClock.getClockAntiScale();
1d7277f3
MK
796 }
797
798 /**
799 * @param cycles
800 * clock cycles since boot
801 * @return time in nanoseconds UTC offset
486efb2e 802 * @since 2.0
1d7277f3
MK
803 */
804 public long timestampCyclesToNanos(long cycles) {
805 long retVal = cycles + getOffset();
806 /*
807 * this fix is since quite often the offset will be > than 53 bits and
808 * therefore the conversion will be lossy
809 */
810 if (clockNeedsScale()) {
811 retVal = (long) (retVal * getTimeScale());
812 }
813 return retVal;
814 }
815
816 /**
817 * @param nanos
818 * time in nanoseconds UTC offset
819 * @return clock cycles since boot.
486efb2e 820 * @since 2.0
1d7277f3
MK
821 */
822 public long timestampNanoToCycles(long nanos) {
823 long retVal;
824 /*
825 * this fix is since quite often the offset will be > than 53 bits and
826 * therefore the conversion will be lossy
827 */
828 if (clockNeedsScale()) {
829 retVal = (long) (nanos * getInverseTimeScale());
830 } else {
831 retVal = nanos;
832 }
833 return retVal - getOffset();
ce2388e0
FC
834 }
835
4c9d2941
MK
836 /**
837 * Adds a callsite
838 *
839 * @param eventName
840 * the event name of the callsite
841 * @param funcName
842 * the name of the callsite function
843 * @param ip
844 * the ip of the callsite
845 * @param fileName
846 * the filename of the callsite
847 * @param lineNumber
848 * the line number of the callsite
849 */
850 public void addCallsite(String eventName, String funcName, long ip,
851 String fileName, long lineNumber) {
852 final CTFCallsite cs = new CTFCallsite(eventName, funcName, ip,
853 fileName, lineNumber);
fe75d403 854 TreeSet<CTFCallsite> csl = fCallsitesByName.get(eventName);
4c9d2941 855 if (csl == null) {
fe75d403
MK
856 csl = new TreeSet<>(fCtfCallsiteComparator);
857 fCallsitesByName.put(eventName, csl);
4c9d2941
MK
858 }
859
890f9136 860 csl.add(cs);
4c9d2941 861
fe75d403 862 fCallsitesByIP.add(cs);
4c9d2941
MK
863 }
864
865 /**
890f9136 866 * Gets the set of callsites associated to an event name. O(1)
4c9d2941
MK
867 *
868 * @param eventName
869 * the event name
890f9136
SD
870 * @return the callsite set can be empty
871 * @since 3.0
4c9d2941 872 */
890f9136 873 public TreeSet<CTFCallsite> getCallsiteCandidates(String eventName) {
fe75d403 874 TreeSet<CTFCallsite> retVal = fCallsitesByName.get(eventName);
890f9136 875 if (retVal == null) {
fe75d403 876 retVal = new TreeSet<>(fCtfCallsiteComparator);
4c9d2941
MK
877 }
878 return retVal;
879 }
880
881 /**
882 * The I'm feeling lucky of getCallsiteCandidates O(1)
883 *
884 * @param eventName
885 * the event name
886 * @return the first callsite that has that event name, can be null
887 * @since 1.2
888 */
889 public CTFCallsite getCallsite(String eventName) {
fe75d403 890 TreeSet<CTFCallsite> callsites = fCallsitesByName.get(eventName);
60fb38b8 891 if (callsites != null) {
890f9136 892 return callsites.first();
60fb38b8
PT
893 }
894 return null;
4c9d2941
MK
895 }
896
897 /**
898 * Gets a callsite from the instruction pointer O(log(n))
899 *
900 * @param ip
901 * the instruction pointer to lookup
902 * @return the callsite just before that IP in the list remember the IP is
903 * backwards on X86, can be null if no callsite is before the IP.
904 * @since 1.2
905 */
906 public CTFCallsite getCallsite(long ip) {
907 CTFCallsite cs = new CTFCallsite(null, null, ip, null, 0L);
fe75d403 908 return fCallsitesByIP.ceiling(cs);
4c9d2941
MK
909 }
910
911 /**
912 * Gets a callsite using the event name and instruction pointer O(log(n))
913 *
914 * @param eventName
915 * the name of the event
916 * @param ip
917 * the instruction pointer
918 * @return the closest matching callsite, can be null
919 */
920 public CTFCallsite getCallsite(String eventName, long ip) {
fe75d403 921 final TreeSet<CTFCallsite> candidates = fCallsitesByName.get(eventName);
4c9d2941 922 final CTFCallsite dummyCs = new CTFCallsite(null, null, ip, null, -1);
890f9136
SD
923 final CTFCallsite callsite = candidates.ceiling(dummyCs);
924 if (callsite == null) {
925 return candidates.floor(dummyCs);
4c9d2941 926 }
890f9136 927 return callsite;
4c9d2941 928 }
866e5b51 929}
c88e827d
AM
930
931class MetadataFileFilter implements FileFilter {
932
933 @Override
934 public boolean accept(File pathname) {
935 if (pathname.isDirectory()) {
936 return false;
937 }
938 if (pathname.isHidden()) {
939 return false;
940 }
941 if (pathname.getName().equals("metadata")) { //$NON-NLS-1$
942 return false;
943 }
944 return true;
945 }
946
947}
948
debcffff 949class MetadataComparator implements Comparator<File>, Serializable {
c88e827d 950
8fd82db5
FC
951 private static final long serialVersionUID = 1L;
952
c88e827d
AM
953 @Override
954 public int compare(File o1, File o2) {
955 return o1.getName().compareTo(o2.getName());
956 }
957}
This page took 0.091627 seconds and 5 git commands to generate.