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