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