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