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