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