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