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