ctf: Make CTFTrace and its reader classes AutoCloseable
[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 // Invoke GC to release MappedByteBuffer objects (Java bug JDK-4724038)
249 System.gc();
250 }
251
252 // ------------------------------------------------------------------------
253 // Getters/Setters/Predicates
254 // ------------------------------------------------------------------------
255
256 /**
257 * Gets an event declaration hash map for a given streamID
258 *
259 * @param streamId
260 * The ID of the stream from which to read
261 * @return The Hash map with the event declarations
262 * @since 2.0
263 */
264 public Map<Long, IEventDeclaration> getEvents(Long streamId) {
265 return fStreams.get(streamId).getEvents();
266 }
267
268 /**
269 * Gets an event Declaration hashmap for a given StreamInput
270 *
271 * @param id
272 * the StreamInput
273 * @return an empty hashmap, please see deprecated
274 * @since 2.0
275 * @deprecated You should be using
276 * {@link StreamInputReader#getEventDefinitions()} instead.
277 */
278 @Deprecated
279 public Map<Long, EventDefinition> getEventDefs(StreamInput id) {
280 return new HashMap<>();
281 }
282
283 /**
284 * Get an event by it's ID
285 *
286 * @param streamId
287 * The ID of the stream from which to read
288 * @param id
289 * the ID of the event
290 * @return the event declaration
291 * @since 2.0
292 */
293 public IEventDeclaration getEventType(long streamId, long id) {
294 return getEvents(streamId).get(id);
295 }
296
297 /**
298 * Method getStream gets the stream for a given id
299 *
300 * @param id
301 * Long the id of the stream
302 * @return Stream the stream that we need
303 * @since 2.0
304 */
305 public Stream getStream(Long id) {
306 return fStreams.get(id);
307 }
308
309 /**
310 * Method nbStreams gets the number of available streams
311 *
312 * @return int the number of streams
313 */
314 public int nbStreams() {
315 return fStreams.size();
316 }
317
318 /**
319 * Method setMajor sets the major version of the trace (DO NOT USE)
320 *
321 * @param major
322 * long the major version
323 */
324 public void setMajor(long major) {
325 fMajor = major;
326 }
327
328 /**
329 * Method setMinor sets the minor version of the trace (DO NOT USE)
330 *
331 * @param minor
332 * long the minor version
333 */
334 public void setMinor(long minor) {
335 fMinor = minor;
336 }
337
338 /**
339 * Method setUUID sets the UUID of a trace
340 *
341 * @param uuid
342 * UUID
343 */
344 public void setUUID(UUID uuid) {
345 fUuid = uuid;
346 }
347
348 /**
349 * Method setByteOrder sets the byte order
350 *
351 * @param byteOrder
352 * ByteOrder of the trace, can be little-endian or big-endian
353 */
354 public void setByteOrder(ByteOrder byteOrder) {
355 fByteOrder = byteOrder;
356 }
357
358 /**
359 * Method setPacketHeader sets the packet header of a trace (DO NOT USE)
360 *
361 * @param packetHeader
362 * StructDeclaration the header in structdeclaration form
363 */
364 public void setPacketHeader(StructDeclaration packetHeader) {
365 fPacketHeaderDecl = packetHeader;
366 }
367
368 /**
369 * Method majorIsSet is the major version number set?
370 *
371 * @return boolean is the major set?
372 * @since 3.0
373 */
374 public boolean majorIsSet() {
375 return fMajor != null;
376 }
377
378 /**
379 * Method minorIsSet. is the minor version number set?
380 *
381 * @return boolean is the minor set?
382 */
383 public boolean minorIsSet() {
384 return fMinor != null;
385 }
386
387 /**
388 * Method UUIDIsSet is the UUID set?
389 *
390 * @return boolean is the UUID set?
391 * @since 2.0
392 */
393 public boolean uuidIsSet() {
394 return fUuid != null;
395 }
396
397 /**
398 * Method byteOrderIsSet is the byteorder set?
399 *
400 * @return boolean is the byteorder set?
401 */
402 public boolean byteOrderIsSet() {
403 return fByteOrder != null;
404 }
405
406 /**
407 * Method packetHeaderIsSet is the packet header set?
408 *
409 * @return boolean is the packet header set?
410 */
411 public boolean packetHeaderIsSet() {
412 return fPacketHeaderDecl != null;
413 }
414
415 /**
416 * Method getUUID gets the trace UUID
417 *
418 * @return UUID gets the trace UUID
419 */
420 public UUID getUUID() {
421 return fUuid;
422 }
423
424 /**
425 * Method getMajor gets the trace major version
426 *
427 * @return long gets the trace major version
428 */
429 public long getMajor() {
430 return fMajor;
431 }
432
433 /**
434 * Method getMinor gets the trace minor version
435 *
436 * @return long gets the trace minor version
437 */
438 public long getMinor() {
439 return fMinor;
440 }
441
442 /**
443 * Method getByteOrder gets the trace byte order
444 *
445 * @return ByteOrder gets the trace byte order
446 */
447 public final ByteOrder getByteOrder() {
448 return fByteOrder;
449 }
450
451 /**
452 * Method getPacketHeader gets the trace packet header
453 *
454 * @return StructDeclaration gets the trace packet header
455 */
456 public StructDeclaration getPacketHeader() {
457 return fPacketHeaderDecl;
458 }
459
460 /**
461 * Method getTraceDirectory gets the trace directory
462 *
463 * @return File the path in "File" format.
464 */
465 public File getTraceDirectory() {
466 return fPath;
467 }
468
469 /**
470 * Get all the streams as an iterable.
471 *
472 * @return Iterable<Stream> an iterable over streams.
473 * @since 3.0
474 */
475 public Iterable<Stream> getStreams() {
476 return fStreams.values();
477 }
478
479 /**
480 * Method getPath gets the path of the trace directory
481 *
482 * @return String the path of the trace directory, in string format.
483 * @see java.io.File#getPath()
484 */
485 @Override
486 public String getPath() {
487 return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$
488 }
489
490 // ------------------------------------------------------------------------
491 // Operations
492 // ------------------------------------------------------------------------
493
494 private void addStream(StreamInput s) {
495
496 /*
497 * Copy the events
498 */
499 Iterator<Entry<Long, IEventDeclaration>> it = s.getStream()
500 .getEvents().entrySet().iterator();
501 while (it.hasNext()) {
502 Entry<Long, IEventDeclaration> pairs = it.next();
503 Long eventNum = pairs.getKey();
504 IEventDeclaration eventDec = pairs.getValue();
505 getEvents(s.getStream().getId()).put(eventNum, eventDec);
506 }
507
508 /*
509 * index the trace
510 */
511 s.setupIndex();
512 }
513
514 /**
515 * Tries to open the given file, reads the first packet header of the file
516 * and check its validity. This will add a file to a stream as a streaminput
517 *
518 * @param streamFile
519 * A trace file in the trace directory.
520 * @param index
521 * Which index in the class' streamFileChannel array this file
522 * must use
523 * @throws CTFReaderException
524 * if there is a file error
525 */
526 private Stream openStreamInput(File streamFile) throws CTFReaderException {
527 MappedByteBuffer byteBuffer;
528 BitBuffer streamBitBuffer;
529 Stream stream;
530 FileChannel fc;
531
532 if (!streamFile.canRead()) {
533 throw new CTFReaderException("Unreadable file : " //$NON-NLS-1$
534 + streamFile.getPath());
535 }
536
537 FileInputStream fis = null;
538 try {
539 /* Open the file and get the FileChannel */
540 fis = new FileInputStream(streamFile);
541 fFileInputStreams.add(fis);
542 fc = fis.getChannel();
543
544 /* Map one memory page of 4 kiB */
545 byteBuffer = fc.map(MapMode.READ_ONLY, 0, (int) Math.min(fc.size(), 4096L));
546 } catch (IOException e) {
547 if (fis != null) {
548 fFileInputStreams.remove(fis);
549 }
550 /* Shouldn't happen at this stage if every other check passed */
551 throw new CTFReaderException(e);
552 }
553
554 /* Create a BitBuffer with this mapping and the trace byte order */
555 streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
556
557 if (fPacketHeaderDef != null) {
558 /* Read the packet header */
559 fPacketHeaderDef.read(streamBitBuffer);
560
561 /* Check the magic number */
562 IntegerDefinition magicDef = (IntegerDefinition) fPacketHeaderDef
563 .lookupDefinition("magic"); //$NON-NLS-1$
564 int magic = (int) magicDef.getValue();
565 if (magic != Utils.CTF_MAGIC) {
566 throw new CTFReaderException("CTF magic mismatch"); //$NON-NLS-1$
567 }
568
569 /* Check UUID */
570 ArrayDefinition uuidDef = (ArrayDefinition) fPacketHeaderDef
571 .lookupDefinition("uuid"); //$NON-NLS-1$
572 if (uuidDef != null) {
573 byte[] uuidArray = new byte[Utils.UUID_LEN];
574
575 for (int i = 0; i < Utils.UUID_LEN; i++) {
576 IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
577 .getElem(i);
578 uuidArray[i] = (byte) uuidByteDef.getValue();
579 }
580
581 UUID otheruuid = Utils.makeUUID(uuidArray);
582
583 if (!fUuid.equals(otheruuid)) {
584 throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
585 }
586 }
587
588 /* Read the stream ID */
589 Definition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
590
591 if (streamIDDef instanceof IntegerDefinition) { // this doubles as a
592 // null check
593 long streamID = ((IntegerDefinition) streamIDDef).getValue();
594 stream = fStreams.get(streamID);
595 } else {
596 /* No stream_id in the packet header */
597 stream = fStreams.get(null);
598 }
599
600 } else {
601 /* No packet header, we suppose there is only one stream */
602 stream = fStreams.get(null);
603 }
604
605 if (stream == null) {
606 throw new CTFReaderException("Unexpected end of stream"); //$NON-NLS-1$
607 }
608
609 /* Create the stream input */
610 StreamInput streamInput = new StreamInput(stream, fc, streamFile);
611
612 /* Add a reference to the streamInput in the stream */
613 stream.addInput(streamInput);
614
615 return stream;
616 }
617
618 /**
619 * Looks up a definition from packet
620 *
621 * @param lookupPath
622 * String
623 * @return Definition
624 * @see org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope#lookupDefinition(String)
625 */
626 @Override
627 public Definition lookupDefinition(String lookupPath) {
628 if (lookupPath.equals("trace.packet.header")) { //$NON-NLS-1$
629 return fPacketHeaderDef;
630 }
631 return null;
632 }
633
634 /**
635 * Add a new stream file to support new streams while the trace is being
636 * read.
637 *
638 * @param streamFile
639 * the file of the stream
640 * @throws CTFReaderException
641 * A stream had an issue being read
642 * @since 3.0
643 */
644 public void addStreamFile(File streamFile) throws CTFReaderException {
645 openStreamInput(streamFile);
646 }
647
648 /**
649 * Registers a new stream to the trace.
650 *
651 * @param stream
652 * A stream object.
653 * @throws ParseException
654 * If there was some problem reading the metadata
655 * @since 2.0
656 */
657 public void addStream(Stream stream) throws ParseException {
658
659 /*
660 * Init if not done before
661 */
662 init();
663
664 /*
665 * If there is already a stream without id (the null key), it must be
666 * the only one
667 */
668 if (fStreams.get(null) != null) {
669 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
670 }
671
672 /*
673 * If the stream we try to add has the null key, it must be the only
674 * one. Thus, if the streams container is not empty, it is not valid.
675 */
676 if ((stream.getId() == null) && (fStreams.size() != 0)) {
677 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
678 }
679
680 /*
681 * If a stream with the same ID already exists, it is not valid.
682 */
683 Stream existingStream = fStreams.get(stream.getId());
684 if (existingStream != null) {
685 throw new ParseException("Stream id already exists"); //$NON-NLS-1$
686 }
687
688 /* This stream is valid and has a unique id. */
689 fStreams.put(stream.getId(), stream);
690 }
691
692 /**
693 * Gets the Environment variables from the trace metadata (See CTF spec)
694 *
695 * @return The environment variables in the form of an unmodifiable map
696 * (key, value)
697 * @since 2.0
698 */
699 public Map<String, String> getEnvironment() {
700 return Collections.unmodifiableMap(fEnvironment);
701 }
702
703 /**
704 * Add a variable to the environment variables
705 *
706 * @param varName
707 * the name of the variable
708 * @param varValue
709 * the value of the variable
710 */
711 public void addEnvironmentVar(String varName, String varValue) {
712 fEnvironment.put(varName, varValue);
713 }
714
715 /**
716 * Add a clock to the clock list
717 *
718 * @param nameValue
719 * the name of the clock (full name with scope)
720 * @param ctfClock
721 * the clock
722 */
723 public void addClock(String nameValue, CTFClock ctfClock) {
724 fClocks.put(nameValue, ctfClock);
725 }
726
727 /**
728 * gets the clock with a specific name
729 *
730 * @param name
731 * the name of the clock.
732 * @return the clock
733 */
734 public CTFClock getClock(String name) {
735 return fClocks.get(name);
736 }
737
738 /**
739 * gets the clock if there is only one. (this is 100% of the use cases as of
740 * June 2012)
741 *
742 * @return the clock
743 */
744 public final CTFClock getClock() {
745 if (fClocks.size() == 1) {
746 fSingleClock = fClocks.get(fClocks.keySet().iterator().next());
747 return fSingleClock;
748 }
749 return null;
750 }
751
752 /**
753 * gets the time offset of a clock with respect to UTC in nanoseconds
754 *
755 * @return the time offset of a clock with respect to UTC in nanoseconds
756 */
757 public final long getOffset() {
758 if (getClock() == null) {
759 return 0;
760 }
761 return fSingleClock.getClockOffset();
762 }
763
764 /**
765 * gets the time offset of a clock with respect to UTC in nanoseconds
766 *
767 * @return the time offset of a clock with respect to UTC in nanoseconds
768 */
769 private double getTimeScale() {
770 if (getClock() == null) {
771 return 1.0;
772 }
773 return fSingleClock.getClockScale();
774 }
775
776 /**
777 * Does the trace need to time scale?
778 *
779 * @return if the trace is in ns or cycles.
780 */
781 private boolean clockNeedsScale() {
782 if (getClock() == null) {
783 return false;
784 }
785 return fSingleClock.isClockScaled();
786 }
787
788 /**
789 * the inverse clock for returning to a scale.
790 *
791 * @return 1.0 / scale
792 */
793 private double getInverseTimeScale() {
794 if (getClock() == null) {
795 return 1.0;
796 }
797 return fSingleClock.getClockAntiScale();
798 }
799
800 /**
801 * @param cycles
802 * clock cycles since boot
803 * @return time in nanoseconds UTC offset
804 * @since 2.0
805 */
806 public long timestampCyclesToNanos(long cycles) {
807 long retVal = cycles + getOffset();
808 /*
809 * this fix is since quite often the offset will be > than 53 bits and
810 * therefore the conversion will be lossy
811 */
812 if (clockNeedsScale()) {
813 retVal = (long) (retVal * getTimeScale());
814 }
815 return retVal;
816 }
817
818 /**
819 * @param nanos
820 * time in nanoseconds UTC offset
821 * @return clock cycles since boot.
822 * @since 2.0
823 */
824 public long timestampNanoToCycles(long nanos) {
825 long retVal;
826 /*
827 * this fix is since quite often the offset will be > than 53 bits and
828 * therefore the conversion will be lossy
829 */
830 if (clockNeedsScale()) {
831 retVal = (long) (nanos * getInverseTimeScale());
832 } else {
833 retVal = nanos;
834 }
835 return retVal - getOffset();
836 }
837
838 /**
839 * Adds a callsite
840 *
841 * @param eventName
842 * the event name of the callsite
843 * @param funcName
844 * the name of the callsite function
845 * @param ip
846 * the ip of the callsite
847 * @param fileName
848 * the filename of the callsite
849 * @param lineNumber
850 * the line number of the callsite
851 */
852 public void addCallsite(String eventName, String funcName, long ip,
853 String fileName, long lineNumber) {
854 final CTFCallsite cs = new CTFCallsite(eventName, funcName, ip,
855 fileName, lineNumber);
856 TreeSet<CTFCallsite> csl = fCallsitesByName.get(eventName);
857 if (csl == null) {
858 csl = new TreeSet<>(fCtfCallsiteComparator);
859 fCallsitesByName.put(eventName, csl);
860 }
861
862 csl.add(cs);
863
864 fCallsitesByIP.add(cs);
865 }
866
867 /**
868 * Gets the set of callsites associated to an event name. O(1)
869 *
870 * @param eventName
871 * the event name
872 * @return the callsite set can be empty
873 * @since 3.0
874 */
875 public TreeSet<CTFCallsite> getCallsiteCandidates(String eventName) {
876 TreeSet<CTFCallsite> retVal = fCallsitesByName.get(eventName);
877 if (retVal == null) {
878 retVal = new TreeSet<>(fCtfCallsiteComparator);
879 }
880 return retVal;
881 }
882
883 /**
884 * The I'm feeling lucky of getCallsiteCandidates O(1)
885 *
886 * @param eventName
887 * the event name
888 * @return the first callsite that has that event name, can be null
889 * @since 1.2
890 */
891 public CTFCallsite getCallsite(String eventName) {
892 TreeSet<CTFCallsite> callsites = fCallsitesByName.get(eventName);
893 if (callsites != null) {
894 return callsites.first();
895 }
896 return null;
897 }
898
899 /**
900 * Gets a callsite from the instruction pointer O(log(n))
901 *
902 * @param ip
903 * the instruction pointer to lookup
904 * @return the callsite just before that IP in the list remember the IP is
905 * backwards on X86, can be null if no callsite is before the IP.
906 * @since 1.2
907 */
908 public CTFCallsite getCallsite(long ip) {
909 CTFCallsite cs = new CTFCallsite(null, null, ip, null, 0L);
910 return fCallsitesByIP.ceiling(cs);
911 }
912
913 /**
914 * Gets a callsite using the event name and instruction pointer O(log(n))
915 *
916 * @param eventName
917 * the name of the event
918 * @param ip
919 * the instruction pointer
920 * @return the closest matching callsite, can be null
921 */
922 public CTFCallsite getCallsite(String eventName, long ip) {
923 final TreeSet<CTFCallsite> candidates = fCallsitesByName.get(eventName);
924 final CTFCallsite dummyCs = new CTFCallsite(null, null, ip, null, -1);
925 final CTFCallsite callsite = candidates.ceiling(dummyCs);
926 if (callsite == null) {
927 return candidates.floor(dummyCs);
928 }
929 return callsite;
930 }
931 }
932
933 class MetadataFileFilter implements FileFilter {
934
935 @Override
936 public boolean accept(File pathname) {
937 if (pathname.isDirectory()) {
938 return false;
939 }
940 if (pathname.isHidden()) {
941 return false;
942 }
943 if (pathname.getName().equals("metadata")) { //$NON-NLS-1$
944 return false;
945 }
946 return true;
947 }
948
949 }
950
951 class MetadataComparator implements Comparator<File>, Serializable {
952
953 private static final long serialVersionUID = 1L;
954
955 @Override
956 public int compare(File o1, File o2) {
957 return o1.getName().compareTo(o2.getName());
958 }
959 }
This page took 0.061736 seconds and 6 git commands to generate.