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