Fix endless loop in Resources view when trace is disposed
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFTrace.java
CommitLineData
866e5b51
FC
1/*******************************************************************************
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
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 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Alexandre Montplaisir - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.ctf.core.trace;
14
15import java.io.File;
16import java.io.FileFilter;
17import java.io.FileInputStream;
18import java.io.IOException;
debcffff 19import java.io.Serializable;
866e5b51
FC
20import java.nio.ByteOrder;
21import java.nio.MappedByteBuffer;
22import java.nio.channels.FileChannel;
23import java.nio.channels.FileChannel.MapMode;
24import java.util.Arrays;
4c9d2941 25import java.util.Collections;
866e5b51
FC
26import java.util.Comparator;
27import java.util.HashMap;
aa572e22 28import java.util.Iterator;
d0d3aa1b
AM
29import java.util.LinkedList;
30import java.util.List;
4c9d2941 31import java.util.ListIterator;
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;
aa572e22 40import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
788ddcbc 41import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
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;
ce2388e0 49import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
788ddcbc 50import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndex;
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 /*
66 * (non-Javadoc)
debcffff 67 *
866e5b51
FC
68 * @see java.lang.Object#toString()
69 */
70 @SuppressWarnings("nls")
71 @Override
72 public String toString() {
73 /* Only for debugging, shouldn't be externalized */
74 return "CTFTrace [path=" + path + ", major=" + major + ", minor="
75 + minor + ", uuid=" + uuid + "]";
76 }
77
78 /**
79 * The trace directory on the filesystem.
80 */
81 private final File path;
82
83 /**
84 * The metadata parsing object.
85 */
86 private final Metadata metadata;
87
88 /**
89 * Major CTF version number
90 */
91 private Long major;
92
93 /**
94 * Minor CTF version number
95 */
96 private Long minor;
97
98 /**
99 * Trace UUID
100 */
101 private UUID uuid;
102
103 /**
104 * Trace byte order
105 */
106 private ByteOrder byteOrder;
107
108 /**
109 * Packet header structure declaration
110 */
debcffff 111 private StructDeclaration packetHeaderDecl = null;
866e5b51 112
1d7277f3
MK
113 /**
114 * The clock of the trace
115 */
116 private CTFClock singleClock;
117
866e5b51
FC
118 /**
119 * Packet header structure definition
debcffff 120 *
866e5b51
FC
121 * This is only used when opening the trace files, to read the first packet
122 * header and see if they are valid trace files.
123 */
124 private StructDefinition packetHeaderDef;
125
126 /**
127 * Collection of streams contained in the trace.
128 */
791072b0 129 private final Map<Long, Stream> streams = new HashMap<Long, Stream>();
866e5b51
FC
130
131 /**
132 * Collection of environment variables set by the tracer
133 */
791072b0 134 private final Map<String, String> environment = new HashMap<String, String>();
866e5b51
FC
135
136 /**
137 * Collection of all the clocks in a system.
138 */
791072b0 139 private final Map<String, CTFClock> clocks = new HashMap<String, CTFClock>();
866e5b51 140
26ea03d2 141 /** FileChannels to the streams */
791072b0 142 private final List<FileChannel> streamFileChannels = new LinkedList<FileChannel>();
26ea03d2 143
c88e827d
AM
144 /** Handlers for the metadata files */
145 private final static FileFilter metadataFileFilter = new MetadataFileFilter();
8ecc80f3
MK
146 private final static Comparator<File> metadataComparator = new MetadataComparator(); // $codepro.audit.disable
147 // fieldJavadoc
866e5b51 148
aa572e22 149 /** map of all the event types */
791072b0 150 private final Map<Long,HashMap<Long, EventDeclaration>> eventDecs = new HashMap<Long, HashMap<Long,EventDeclaration>>();
788ddcbc 151 /** map of all the event types */
791072b0 152 private final Map<StreamInput,HashMap<Long, EventDefinition>> eventDefs = new HashMap<StreamInput, HashMap<Long,EventDefinition>>();
788ddcbc 153 /** map of all the indexes */
791072b0 154 private final Map<StreamInput, StreamInputPacketIndex> indexes = new HashMap<StreamInput, StreamInputPacketIndex>();
788ddcbc 155
4c9d2941 156 /** Callsite helpers */
791072b0 157 private Map<String, LinkedList<CTFCallsite>> callsitesByName = new HashMap<String, LinkedList<CTFCallsite>>();
4c9d2941
MK
158 /** Callsite helpers */
159 private TreeSet<CTFCallsite> callsitesByIP = new TreeSet<CTFCallsite>();
788ddcbc
MK
160
161
aa572e22 162
866e5b51
FC
163 // ------------------------------------------------------------------------
164 // Constructors
165 // ------------------------------------------------------------------------
166
167 /**
168 * Trace constructor.
debcffff 169 *
866e5b51 170 * @param path
be6df2d8
AM
171 * Filesystem path of the trace directory
172 * @throws CTFReaderException
173 * If no CTF trace was found at the path
866e5b51
FC
174 */
175 public CTFTrace(String path) throws CTFReaderException {
176 this(new File(path));
aa572e22 177
866e5b51
FC
178 }
179
180 /**
181 * Trace constructor.
debcffff 182 *
866e5b51
FC
183 * @param path
184 * Filesystem path of the trace directory.
185 * @throws CTFReaderException
be6df2d8 186 * If no CTF trace was found at the path
866e5b51 187 */
866e5b51
FC
188 public CTFTrace(File path) throws CTFReaderException {
189 this.path = path;
c88e827d 190 this.metadata = new Metadata(this);
866e5b51 191
c88e827d 192 /* Set up the internal containers for this trace */
8a95ce5a
BH
193 if (!this.path.exists()) {
194 throw new CTFReaderException("Trace (" + path.getPath() + ") doesn't exist. Deleted or moved?"); //$NON-NLS-1$ //$NON-NLS-2$
195 }
d0d3aa1b
AM
196
197 if (!this.path.isDirectory()) {
198 throw new CTFReaderException("Path must be a valid directory"); //$NON-NLS-1$
199 }
c88e827d
AM
200
201 /* Open and parse the metadata file */
202 metadata.parse();
203
c88e827d
AM
204 /* Open all the trace files */
205 /* Create the definitions needed to read things from the files */
206 if (packetHeaderDecl != null) {
207 packetHeaderDef = packetHeaderDecl.createDefinition(this,
208 "packet.header"); //$NON-NLS-1$
209 }
210
211 /* List files not called metadata and not hidden. */
212 File[] files = path.listFiles(metadataFileFilter);
213 Arrays.sort(files, metadataComparator);
c88e827d 214 /* Try to open each file */
d0d3aa1b
AM
215 for (File streamFile : files) {
216 openStreamInput(streamFile);
c88e827d 217 }
788ddcbc 218
c88e827d
AM
219 /* Create their index */
220 for (Map.Entry<Long, Stream> stream : streams.entrySet()) {
221 Set<StreamInput> inputs = stream.getValue().getStreamInputs();
222 for (StreamInput s : inputs) {
aa572e22
MK
223 /*
224 * Copy the events
225 */
226 Iterator<Entry<Long, EventDeclaration>> it = s.getStream()
227 .getEvents().entrySet().iterator();
228 while (it.hasNext()) {
229 Map.Entry<Long, EventDeclaration> pairs = it.next();
230 Long eventNum = pairs.getKey();
231 EventDeclaration eventDec = pairs.getValue();
788ddcbc 232 getEvents(s.getStream().getId()).put(eventNum, eventDec);
aa572e22
MK
233 }
234
235 /*
236 * index the trace
237 */
bfe038ff 238 s.setupIndex();
c88e827d
AM
239 }
240 }
866e5b51
FC
241 }
242
26ea03d2 243 @Override
8ecc80f3 244 protected void finalize() throws Throwable {
26ea03d2
AM
245 /* If this trace gets closed, release the descriptors to the streams */
246 for (FileChannel fc : streamFileChannels) {
247 if (fc != null) {
248 try {
249 fc.close();
250 } catch (IOException e) {
aa572e22 251 // do nothing it's ok, we tried to close it.
26ea03d2
AM
252 }
253 }
254 }
787bc247
MK
255 super.finalize();
256
26ea03d2
AM
257 }
258
866e5b51
FC
259 // ------------------------------------------------------------------------
260 // Getters/Setters/Predicates
261 // ------------------------------------------------------------------------
262
aa572e22 263 /**
be6df2d8
AM
264 * Gets an event declaration hash map for a given streamID
265 *
266 * @param streamId
267 * The ID of the stream from which to read
268 * @return The Hash map with the event declarations
788ddcbc 269 */
be6df2d8
AM
270 public HashMap<Long, EventDeclaration> getEvents(Long streamId) {
271 return eventDecs.get(streamId);
788ddcbc
MK
272 }
273
274 /**
275 * Gets an index for a given StreamInput
276 * @param id the StreamInput
277 * @return The index
aa572e22 278 */
486efb2e 279 StreamInputPacketIndex getIndex(StreamInput id){
788ddcbc
MK
280 if(! indexes.containsKey(id)){
281 indexes.put(id, new StreamInputPacketIndex());
282 }
283 return indexes.get(id);
aa572e22
MK
284 }
285
286 /**
788ddcbc
MK
287 * Gets an event Declaration hashmap for a given StreamInput
288 * @param id the StreamInput
289 * @return the hashmap with the event definitions
290 */
291 public HashMap<Long, EventDefinition> getEventDefs(StreamInput id) {
292 if(! eventDefs.containsKey(id)){
293 eventDefs.put(id, new HashMap<Long, EventDefinition>());
294 }
295 return eventDefs.get(id);
296 }
297
298 /**
299 * Get an event by it's ID
aa572e22 300 *
be6df2d8
AM
301 * @param streamId
302 * The ID of the stream from which to read
788ddcbc
MK
303 * @param id
304 * the ID of the event
305 * @return the event declaration
aa572e22 306 */
788ddcbc
MK
307 public EventDeclaration getEventType(long streamId, long id) {
308 return getEvents(streamId).get(id);
aa572e22
MK
309 }
310
866e5b51
FC
311 /**
312 * Method getStream gets the stream for a given id
debcffff 313 *
866e5b51
FC
314 * @param id
315 * Long the id of the stream
316 * @return Stream the stream that we need
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 */
d0d3aa1b
AM
528 fc = new FileInputStream(streamFile).getChannel();
529 streamFileChannels.add(fc);
866e5b51
FC
530
531 /* Map one memory page of 4 kiB */
d0d3aa1b 532 byteBuffer = fc.map(MapMode.READ_ONLY, 0, 4096);
866e5b51
FC
533 } catch (IOException e) {
534 /* Shouldn't happen at this stage if every other check passed */
535 throw new CTFReaderException();
536 }
537
538 /* Create a BitBuffer with this mapping and the trace byte order */
539 streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
540
541 if (packetHeaderDef != null) {
542 /* Read the packet header */
543 packetHeaderDef.read(streamBitBuffer);
544
545 /* Check the magic number */
aa572e22
MK
546 IntegerDefinition magicDef = (IntegerDefinition) packetHeaderDef
547 .lookupDefinition("magic"); //$NON-NLS-1$
866e5b51
FC
548 int magic = (int) magicDef.getValue();
549 if (magic != Utils.CTF_MAGIC) {
550 throw new CTFReaderException("CTF magic mismatch"); //$NON-NLS-1$
551 }
552
553 /* Check UUID */
aa572e22
MK
554 ArrayDefinition uuidDef = (ArrayDefinition) packetHeaderDef
555 .lookupDefinition("uuid"); //$NON-NLS-1$
866e5b51
FC
556 if (uuidDef != null) {
557 byte[] uuidArray = new byte[Utils.UUID_LEN];
558
559 for (int i = 0; i < Utils.UUID_LEN; i++) {
aa572e22
MK
560 IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
561 .getElem(i);
866e5b51
FC
562 uuidArray[i] = (byte) uuidByteDef.getValue();
563 }
564
565 UUID otheruuid = Utils.makeUUID(uuidArray);
566
567 if (!this.uuid.equals(otheruuid)) {
568 throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
569 }
570 }
571
1fbaecd1
AM
572 /* Read the stream ID */
573 Definition streamIDDef = packetHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
574
575 if (streamIDDef instanceof IntegerDefinition) { //this doubles as a null check
576 long streamID = ((IntegerDefinition) streamIDDef).getValue();
577 stream = streams.get(streamID);
578 } else {
579 /* No stream_id in the packet header */
580 stream = streams.get(null);
581 }
582
866e5b51
FC
583 } else {
584 /* No packet header, we suppose there is only one stream */
d0d3aa1b
AM
585 stream = streams.get(null);
586 }
866e5b51 587
d0d3aa1b
AM
588 /* Create the stream input */
589 StreamInput streamInput = new StreamInput(stream, fc, streamFile);
866e5b51 590
d0d3aa1b
AM
591 /* Add a reference to the streamInput in the stream */
592 stream.addInput(streamInput);
866e5b51
FC
593 }
594
595 /**
596 * Looks up a definition from packet
debcffff 597 *
866e5b51
FC
598 * @param lookupPath
599 * String
600 * @return Definition
601 * @see org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope#lookupDefinition(String)
602 */
603 @Override
604 public Definition lookupDefinition(String lookupPath) {
605 if (lookupPath.equals("trace.packet.header")) { //$NON-NLS-1$
606 return packetHeaderDef;
607 }
608 return null;
609 }
610
611 /**
612 * Adds a new stream to the trace.
debcffff 613 *
866e5b51
FC
614 * @param stream
615 * A stream object.
866e5b51 616 * @throws ParseException
be6df2d8 617 * If there was some problem reading the metadata
866e5b51
FC
618 */
619 public void addStream(Stream stream) throws ParseException {
620
621 /*
622 * If there is already a stream without id (the null key), it must be
623 * the only one
624 */
625 if (streams.get(null) != null) {
626 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
627 }
628
629 /*
1d7277f3
MK
630 * If the stream we try to add has the null key, it must be the only
631 * one. Thus, if the streams container is not empty, it is not valid.
866e5b51
FC
632 */
633 if ((stream.getId() == null) && (streams.size() != 0)) {
634 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
635 }
636
637 /* If a stream with the same ID already exists, it is not valid. */
638 if (streams.get(stream.getId()) != null) {
639 throw new ParseException("Stream id already exists"); //$NON-NLS-1$
640 }
641
642 /* It should be ok now. */
643 streams.put(stream.getId(), stream);
788ddcbc 644 eventDecs.put(stream.getId(), new HashMap<Long,EventDeclaration>());
866e5b51
FC
645 }
646
9ac2eb62
MK
647 /**
648 * gets the Environment variables from the trace metadata (See CTF spec)
791072b0 649 * @return the environment variables in a map form (key value)
486efb2e 650 * @since 2.0
9ac2eb62 651 */
791072b0 652 public Map<String, String> getEnvironment() {
866e5b51
FC
653 return environment;
654 }
655
9ac2eb62
MK
656 /**
657 * Look up a specific environment variable
658 * @param key the key to look for
659 * @return the value of the variable, can be null.
660 */
c88e827d 661 public String lookupEnvironment(String key) {
866e5b51
FC
662 return environment.get(key);
663 }
664
9ac2eb62
MK
665 /**
666 * Add a variable to the environment variables
667 * @param varName the name of the variable
668 * @param varValue the value of the variable
669 */
c88e827d 670 public void addEnvironmentVar(String varName, String varValue) {
866e5b51
FC
671 environment.put(varName, varValue);
672 }
673
9ac2eb62
MK
674 /**
675 * Add a clock to the clock list
676 * @param nameValue the name of the clock (full name with scope)
677 * @param ctfClock the clock
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
685 * @param name the name of the clock.
686 * @return the clock
687 */
c88e827d 688 public CTFClock getClock(String name) {
866e5b51
FC
689 return clocks.get(name);
690 }
691
1d7277f3
MK
692
693
8ecc80f3 694
9ac2eb62 695 /**
1d7277f3
MK
696 * gets the clock if there is only one. (this is 100% of the use cases as of
697 * June 2012)
698 *
9ac2eb62
MK
699 * @return the clock
700 */
8ecc80f3 701 public final CTFClock getClock() {
c88e827d 702 if (clocks.size() == 1) {
1d7277f3 703 singleClock = clocks.get(clocks.keySet().iterator().next());
8ecc80f3 704 return singleClock;
866e5b51
FC
705 }
706 return null;
707 }
708
9ac2eb62
MK
709 /**
710 * gets the time offset of a clock with respect to UTC in nanoseconds
1d7277f3 711 *
9ac2eb62
MK
712 * @return the time offset of a clock with respect to UTC in nanoseconds
713 */
8ecc80f3 714 public final long getOffset() {
c88e827d 715 if (getClock() == null) {
ce2388e0
FC
716 return 0;
717 }
1d7277f3
MK
718 return singleClock.getClockOffset();
719 }
720
721 /**
722 * gets the time offset of a clock with respect to UTC in nanoseconds
723 *
724 * @return the time offset of a clock with respect to UTC in nanoseconds
725 */
726 private final double getTimeScale() {
727 if (getClock() == null) {
728 return 1.0;
729 }
730 return singleClock.getClockScale();
731 }
732
733 /**
734 * Does the trace need to time scale?
735 *
736 * @return if the trace is in ns or cycles.
737 */
738 private final boolean clockNeedsScale() {
739 if (getClock() == null) {
740 return false;
741 }
742 return singleClock.isClockScaled();
743 }
744
745 /**
746 * the inverse clock for returning to a scale.
747 *
748 * @return 1.0 / scale
749 */
750 private final double getInverseTimeScale() {
751 if (getClock() == null) {
752 return 1.0;
753 }
754 return singleClock.getClockAntiScale();
755 }
756
757 /**
758 * @param cycles
759 * clock cycles since boot
760 * @return time in nanoseconds UTC offset
486efb2e 761 * @since 2.0
1d7277f3
MK
762 */
763 public long timestampCyclesToNanos(long cycles) {
764 long retVal = cycles + getOffset();
765 /*
766 * this fix is since quite often the offset will be > than 53 bits and
767 * therefore the conversion will be lossy
768 */
769 if (clockNeedsScale()) {
770 retVal = (long) (retVal * getTimeScale());
771 }
772 return retVal;
773 }
774
775 /**
776 * @param nanos
777 * time in nanoseconds UTC offset
778 * @return clock cycles since boot.
486efb2e 779 * @since 2.0
1d7277f3
MK
780 */
781 public long timestampNanoToCycles(long nanos) {
782 long retVal;
783 /*
784 * this fix is since quite often the offset will be > than 53 bits and
785 * therefore the conversion will be lossy
786 */
787 if (clockNeedsScale()) {
788 retVal = (long) (nanos * getInverseTimeScale());
789 } else {
790 retVal = nanos;
791 }
792 return retVal - getOffset();
ce2388e0
FC
793 }
794
9ac2eb62
MK
795 /**
796 * Does a given stream contain any events?
797 * @param id the stream ID
798 * @return true if the stream has events.
799 */
788ddcbc
MK
800 public boolean hasEvents(Long id){
801 return eventDecs.containsKey(id);
802 }
9ac2eb62
MK
803
804 /**
805 * Add an event declaration map to the events map.
806 * @param id the id of a stream
807 * @return the hashmap containing events.
808 */
788ddcbc
MK
809 public HashMap<Long, EventDeclaration> createEvents(Long id){
810 HashMap<Long, EventDeclaration> value = eventDecs.get(id);
811 if( value == null ) {
812 value = new HashMap<Long, EventDeclaration>();
813 eventDecs.put(id, value);
814 }
815 return value;
816 }
817
4c9d2941
MK
818 /**
819 * Adds a callsite
820 *
821 * @param eventName
822 * the event name of the callsite
823 * @param funcName
824 * the name of the callsite function
825 * @param ip
826 * the ip of the callsite
827 * @param fileName
828 * the filename of the callsite
829 * @param lineNumber
830 * the line number of the callsite
831 */
832 public void addCallsite(String eventName, String funcName, long ip,
833 String fileName, long lineNumber) {
834 final CTFCallsite cs = new CTFCallsite(eventName, funcName, ip,
835 fileName, lineNumber);
836 LinkedList<CTFCallsite> csl = callsitesByName.get(eventName);
837 if (csl == null) {
838 csl = new LinkedList<CTFCallsite>();
839 callsitesByName.put(eventName, csl);
840 }
841
842 ListIterator<CTFCallsite> iter = csl.listIterator();
843 int index = 0;
844 for (; index < csl.size(); index++) {
845 if (iter.next().compareTo(cs) < 0) {
846 break;
847 }
848 }
849
850 csl.add(index, cs);
851
852 callsitesByIP.add(cs);
853 }
854
855 /**
856 * Gets the list of callsites associated to an event name. O(1)
857 *
858 * @param eventName
859 * the event name
860 * @return the callsite list can be empty
861 * @since 1.2
862 */
863 public List<CTFCallsite> getCallsiteCandidates(String eventName) {
864 LinkedList<CTFCallsite> retVal = callsitesByName.get(eventName);
865 if( retVal == null ) {
866 retVal = new LinkedList<CTFCallsite>();
867 }
868 return retVal;
869 }
870
871 /**
872 * The I'm feeling lucky of getCallsiteCandidates O(1)
873 *
874 * @param eventName
875 * the event name
876 * @return the first callsite that has that event name, can be null
877 * @since 1.2
878 */
879 public CTFCallsite getCallsite(String eventName) {
880 return callsitesByName.get(eventName).getFirst();
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) {
907 final LinkedList<CTFCallsite> candidates = callsitesByName.get(eventName);
908 final CTFCallsite dummyCs = new CTFCallsite(null, null, ip, null, -1);
909 final int pos = Collections.binarySearch(candidates, dummyCs)+1;
910 if( pos >= candidates.size()) {
911 return null;
912 }
913 return candidates.get(pos);
914 }
915
866e5b51 916}
c88e827d
AM
917
918class MetadataFileFilter implements FileFilter {
919
920 @Override
921 public boolean accept(File pathname) {
922 if (pathname.isDirectory()) {
923 return false;
924 }
925 if (pathname.isHidden()) {
926 return false;
927 }
928 if (pathname.getName().equals("metadata")) { //$NON-NLS-1$
929 return false;
930 }
931 return true;
932 }
933
934}
935
debcffff 936class MetadataComparator implements Comparator<File>, Serializable {
c88e827d 937
8fd82db5
FC
938 private static final long serialVersionUID = 1L;
939
c88e827d
AM
940 @Override
941 public int compare(File o1, File o2) {
942 return o1.getName().compareTo(o2.getName());
943 }
944}
This page took 0.075466 seconds and 5 git commands to generate.