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