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