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