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