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