Rename xxx.lttng to xxx.lttng.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.core / src / org / eclipse / linuxtools / lttng / trace / LTTngTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2011 Ericsson, MontaVista Software
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made 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 * William Bourque (wbourque@gmail.com) - Initial API and implementation
11 * Yufen Kuo (ykuo@mvista.com) - add support to allow user specify trace library path
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.lttng.trace;
15
16 import java.io.FileNotFoundException;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.Vector;
20
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.linuxtools.lttng.TraceHelper;
23 import org.eclipse.linuxtools.lttng.event.LttngEvent;
24 import org.eclipse.linuxtools.lttng.event.LttngEventContent;
25 import org.eclipse.linuxtools.lttng.event.LttngEventReference;
26 import org.eclipse.linuxtools.lttng.event.LttngEventSource;
27 import org.eclipse.linuxtools.lttng.event.LttngEventType;
28 import org.eclipse.linuxtools.lttng.event.LttngLocation;
29 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
30 import org.eclipse.linuxtools.lttng.exceptions.LttngException;
31 import org.eclipse.linuxtools.lttng.jni.JniEvent;
32 import org.eclipse.linuxtools.lttng.jni.JniMarker;
33 import org.eclipse.linuxtools.lttng.jni.JniTrace;
34 import org.eclipse.linuxtools.lttng.jni.JniTracefile;
35 import org.eclipse.linuxtools.lttng.jni.common.JniTime;
36 import org.eclipse.linuxtools.lttng.jni.exception.JniException;
37 import org.eclipse.linuxtools.lttng.jni.factory.JniTraceFactory;
38 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
39 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
40 import org.eclipse.linuxtools.tmf.trace.ITmfContext;
41 import org.eclipse.linuxtools.tmf.trace.ITmfLocation;
42 import org.eclipse.linuxtools.tmf.trace.TmfCheckpoint;
43 import org.eclipse.linuxtools.tmf.trace.TmfContext;
44 import org.eclipse.linuxtools.tmf.trace.TmfTrace;
45
46 class LTTngTraceException extends LttngException {
47 static final long serialVersionUID = -1636648737081868146L;
48
49 public LTTngTraceException(String errMsg) {
50 super(errMsg);
51 }
52 }
53
54 /**
55 * <b><u>LTTngTrace</u></b>
56 * <p>
57 *
58 * LTTng trace implementation. It accesses the C trace handling library (seeking, reading and parsing) through the JNI
59 * component.
60 */
61 public class LTTngTrace extends TmfTrace<LttngEvent> {
62
63 public static boolean PrintDebug = false;
64 public static boolean UniqueEvent = true;
65
66 private final static boolean SHOW_LTT_DEBUG_DEFAULT = false;
67 private final static boolean IS_PARSING_NEEDED_DEFAULT = !UniqueEvent;
68 private final static int CHECKPOINT_PAGE_SIZE = 50000;
69
70 // Reference to our JNI trace
71 private JniTrace currentJniTrace;
72
73 LttngTimestamp eventTimestamp;
74 LttngEventSource eventSource;
75 LttngEventContent eventContent;
76 LttngEventReference eventReference;
77
78 // The actual event
79 LttngEvent currentLttngEvent;
80
81 // The current location
82 LttngLocation previousLocation;
83
84 LttngEventType eventType;
85
86 // Hashmap of the possible types of events (Tracefile/CPU/Marker in the JNI)
87 HashMap<Integer, LttngEventType> traceTypes;
88
89 // This vector will be used to quickly find a marker name from a position
90 Vector<Integer> traceTypeNames;
91
92 private String traceLibPath;
93
94 public LTTngTrace() {
95 }
96
97 public boolean validate(IProject project, String path) {
98 if (super.validate(project, path)) {
99 String traceLibPath = TraceHelper.getTraceLibDirFromProject(project);
100 try {
101 LTTngTraceVersion version = new LTTngTraceVersion(path, traceLibPath);
102 return version.isValidLttngTrace();
103 } catch (LttngException e) {
104 }
105 }
106 return false;
107 }
108
109 public void initTrace(String path, Class<LttngEvent> eventType) throws FileNotFoundException {
110 initLTTngTrace(path, eventType, CHECKPOINT_PAGE_SIZE, false);
111 }
112
113 public void initTrace(String path, Class<LttngEvent> eventType, int cacheSize) throws FileNotFoundException {
114 initLTTngTrace(path, eventType, cacheSize, false);
115 }
116
117 public void initTrace(String path, Class<LttngEvent> eventType, boolean indexTrace) throws FileNotFoundException {
118 initLTTngTrace(path, eventType, CHECKPOINT_PAGE_SIZE, indexTrace);
119 }
120
121 public void initTrace(String path, Class<LttngEvent> eventType, int cacheSize, boolean indexTrace) throws FileNotFoundException {
122 initLTTngTrace(path, eventType, cacheSize, indexTrace);
123 }
124
125 private void initLTTngTrace(String path, Class<LttngEvent> eventType, int cacheSize, boolean indexTrace) throws FileNotFoundException {
126 super.initTrace(path, eventType, indexTrace);
127 try {
128 currentJniTrace = JniTraceFactory.getJniTrace(path, traceLibPath, SHOW_LTT_DEBUG_DEFAULT);
129 } catch (Exception e) {
130 throw new FileNotFoundException(e.getMessage());
131 }
132
133 // Export all the event types from the JNI side
134 traceTypes = new HashMap<Integer, LttngEventType>();
135 traceTypeNames = new Vector<Integer>();
136 initialiseEventTypes(currentJniTrace);
137
138 // Build the re-used event structure
139 eventTimestamp = new LttngTimestamp();
140 eventSource = new LttngEventSource();
141 this.eventType = new LttngEventType();
142 eventContent = new LttngEventContent(currentLttngEvent);
143 eventReference = new LttngEventReference(this.getName());
144
145 // Create the skeleton event
146 currentLttngEvent = new LttngEvent(this, eventTimestamp, eventSource, this.eventType, eventContent,
147 eventReference, null);
148
149 // Create a new current location
150 previousLocation = new LttngLocation();
151
152 // Set the currentEvent to the eventContent
153 eventContent.setEvent(currentLttngEvent);
154
155 // Set the time range of the trace
156 TmfContext context = seekLocation(null);
157 LttngEvent event = getNextEvent(context);
158 LttngTimestamp startTime = new LttngTimestamp(event.getTimestamp());
159 LttngTimestamp endTime = new LttngTimestamp(currentJniTrace.getEndTime().getTime());
160
161 setTimeRange(new TmfTimeRange(startTime, endTime));
162
163 if (currentJniTrace == null) {
164 System.out.println("Problem");
165 }
166 }
167
168 /**
169 * Default Constructor.
170 * <p>
171 *
172 * @param path
173 * Path to a <b>directory</b> that contain an LTTng trace.
174 *
175 * @exception Exception
176 * (most likely LTTngTraceException or FileNotFoundException)
177 */
178 public LTTngTrace(String path) throws Exception {
179 // Call with "wait for completion" true and "skip indexing" false
180 this(path, null, true, false);
181 }
182
183 /**
184 * Constructor, with control over the indexing.
185 * <p>
186 *
187 * @param path
188 * Path to a <b>directory</b> that contain an LTTng trace.
189 * @param waitForCompletion
190 * Should we wait for indexign to complete before moving on.
191 *
192 * @exception Exception
193 * (most likely LTTngTraceException or FileNotFoundException)
194 */
195 public LTTngTrace(String path, boolean waitForCompletion) throws Exception {
196 // Call with "skip indexing" false
197 this(path, null, waitForCompletion, true);
198 }
199
200 /**
201 * Default constructor, with control over the indexing and possibility to bypass indexation
202 * <p>
203 *
204 * @param path
205 * Path to a <b>directory</b> that contain an LTTng trace.
206 * @param traceLibPath
207 * Path to a <b>directory</b> that contains LTTng trace libraries.
208 * @param waitForCompletion
209 * Should we wait for indexign to complete before moving on.
210 * @param bypassIndexing
211 * Should we bypass indexing completly? This is should only be useful for unit testing.
212 *
213 * @exception Exception
214 * (most likely LTTngTraceException or FileNotFoundException)
215 *
216 */
217 public LTTngTrace(String path, String traceLibPath, boolean waitForCompletion, boolean bypassIndexing)
218 throws Exception {
219 super(path, LttngEvent.class, path, CHECKPOINT_PAGE_SIZE, false);
220 initTrace(path, LttngEvent.class, !bypassIndexing);
221 this.traceLibPath = traceLibPath;
222 }
223
224 /*
225 * Copy constructor is forbidden for LttngEvenmStream
226 */
227 public LTTngTrace(LTTngTrace other) throws Exception {
228 this(other.getPath(), other.getTraceLibPath(), false, true);
229 this.fCheckpoints = other.fCheckpoints;
230 setTimeRange(new TmfTimeRange(new LttngTimestamp(other.getStartTime()), new LttngTimestamp(other.getEndTime())));
231 }
232
233 @Override
234 public LTTngTrace copy() {
235 LTTngTrace returnedTrace = null;
236
237 try {
238 returnedTrace = new LTTngTrace(this);
239 } catch (Exception e) {
240 System.out
241 .println("ERROR : Could not create LTTngTrace copy (createTraceCopy).\nError is : " + e.getStackTrace()); //$NON-NLS-1$
242 }
243
244 return returnedTrace;
245 }
246
247 @Override
248 public synchronized LTTngTrace clone() {
249 LTTngTrace clone = null;
250 try {
251 clone = (LTTngTrace) super.clone();
252 try {
253 clone.currentJniTrace = JniTraceFactory.getJniTrace(getPath(), getTraceLibPath(),
254 SHOW_LTT_DEBUG_DEFAULT);
255 } catch (JniException e) {
256 // e.printStackTrace();
257 }
258
259 // Export all the event types from the JNI side
260 clone.traceTypes = new HashMap<Integer, LttngEventType>();
261 clone.traceTypeNames = new Vector<Integer>();
262 clone.initialiseEventTypes(clone.currentJniTrace);
263
264 // Verify that all those "default constructor" are safe to use
265 clone.eventTimestamp = new LttngTimestamp();
266 clone.eventSource = new LttngEventSource();
267 clone.eventType = new LttngEventType();
268 clone.eventContent = new LttngEventContent(clone.currentLttngEvent);
269 clone.eventReference = new LttngEventReference(this.getName());
270
271 // Create the skeleton event
272 clone.currentLttngEvent = new LttngEvent(this, clone.eventTimestamp, clone.eventSource, clone.eventType,
273 clone.eventContent, clone.eventReference, null);
274
275 // Create a new current location
276 clone.previousLocation = new LttngLocation();
277
278 // Set the currentEvent to the eventContent
279 clone.eventContent.setEvent(clone.currentLttngEvent);
280
281 // Set the start time of the trace
282 setTimeRange(new TmfTimeRange(new LttngTimestamp(clone.currentJniTrace.getStartTime().getTime()),
283 new LttngTimestamp(clone.currentJniTrace.getEndTime().getTime())));
284 } catch (CloneNotSupportedException e) {
285 }
286
287 return clone;
288 }
289
290 public String getTraceLibPath() {
291 return traceLibPath;
292 }
293
294 /*
295 * Fill out the HashMap with "Type" (Tracefile/Marker)
296 *
297 * This should be called at construction once the trace is open
298 */
299 private void initialiseEventTypes(JniTrace trace) {
300 // Work variables
301 LttngEventType tmpType = null;
302 String[] markerFieldsLabels = null;
303
304 String newTracefileKey = null;
305 Integer newMarkerKey = null;
306
307 JniTracefile newTracefile = null;
308 JniMarker newMarker = null;
309
310 // First, obtain an iterator on TRACEFILES of owned by the TRACE
311 Iterator<String> tracefileItr = trace.getTracefilesMap().keySet().iterator();
312
313 while (tracefileItr.hasNext()) {
314 newTracefileKey = tracefileItr.next();
315 newTracefile = trace.getTracefilesMap().get(newTracefileKey);
316
317 // From the TRACEFILE read, obtain its MARKER
318 Iterator<Integer> markerItr = newTracefile.getTracefileMarkersMap().keySet().iterator();
319 while (markerItr.hasNext()) {
320 newMarkerKey = markerItr.next();
321 newMarker = newTracefile.getTracefileMarkersMap().get(newMarkerKey);
322
323 // From the MARKER we can obtain the MARKERFIELDS keys (i.e.
324 // labels)
325 markerFieldsLabels = newMarker.getMarkerFieldsHashMap().keySet()
326 .toArray(new String[newMarker.getMarkerFieldsHashMap().size()]);
327
328 tmpType = new LttngEventType(newTracefile.getTracefileName(), newTracefile.getCpuNumber(),
329 newMarker.getName(), newMarkerKey.intValue(), markerFieldsLabels);
330
331 // Add the type to the map/vector
332 addEventTypeToMap(tmpType);
333 }
334 }
335 }
336
337 /*
338 * Add a new type to the HashMap
339 *
340 * As the hashmap use a key format that is a bit dangerous to use, we should always add using this function.
341 */
342 private void addEventTypeToMap(LttngEventType newEventType) {
343 int newTypeKey = EventTypeKey.getEventTypeHash(newEventType);
344
345 this.traceTypes.put(newTypeKey, newEventType);
346 this.traceTypeNames.add(newTypeKey);
347 }
348
349 /**
350 * Return the latest saved location. Note : Modifying the returned location may result in buggy positionning!
351 *
352 * @return The LttngLocation as it was after the last operation.
353 *
354 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
355 */
356 @Override
357 public synchronized ITmfLocation<?> getCurrentLocation() {
358 return previousLocation;
359 }
360
361 /**
362 * Position the trace to the event at the given location.
363 * <p>
364 * NOTE : Seeking by location is very fast compare to seeking by position but is still slower than "ReadNext", avoid
365 * using it for small interval.
366 *
367 * @param location
368 * Location of the event in the trace. If no event available at this exact location, we will position
369 * ourself to the next one.
370 *
371 * @return The TmfContext that point to this event
372 *
373 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
374 * @see org.eclipse.linuxtools.tmf.trace.TmfContext
375 */
376 @Override
377 public synchronized TmfContext seekLocation(ITmfLocation<?> location) {
378
379 // // [lmcfrch]
380 // lastTime = 0;
381
382 if (PrintDebug) {
383 System.out.println("seekLocation(location) location -> " + location); //$NON-NLS-1$
384 }
385
386 // If the location in context is null, create a new one
387 LttngLocation curLocation = null;
388 if (location == null) {
389 curLocation = new LttngLocation();
390 TmfContext context = seekEvent(curLocation.getOperationTime());
391 context.setRank(ITmfContext.INITIAL_RANK);
392 return context;
393 } else {
394 curLocation = (LttngLocation) location;
395 }
396
397 // *** NOTE :
398 // Update to location should (and will) be done in SeekEvent.
399
400 // The only seek valid in LTTng is with the time, we call
401 // seekEvent(timestamp)
402 TmfContext context = seekEvent(curLocation.getOperationTime());
403
404 return context;
405 }
406
407 /**
408 * Position the trace to the event at the given time.
409 * <p>
410 * NOTE : Seeking by time is very fast compare to seeking by position but is still slower than "ReadNext", avoid
411 * using it for small interval.
412 *
413 * @param timestamp
414 * Time of the event in the trace. If no event available at this exact time, we will position ourself to
415 * the next one.
416 *
417 * @return The TmfContext that point to this event
418 *
419 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
420 * @see org.eclipse.linuxtools.tmf.trace.TmfContext
421 */
422 @Override
423 public synchronized TmfContext seekEvent(TmfTimestamp timestamp) {
424
425 if (PrintDebug) {
426 System.out.println("seekEvent(timestamp) timestamp -> " + timestamp); //$NON-NLS-1$
427 }
428
429 if (currentJniTrace == null) {
430 System.out.println("aie");
431 }
432
433 // Call JNI to seek
434 currentJniTrace.seekToTime(new JniTime(timestamp.getValue()));
435
436 // Save the time at which we seeked
437 previousLocation.setOperationTime(timestamp.getValue());
438 // Set the operation marker as seek, to be able to detect we did "seek"
439 // this event
440 previousLocation.setLastOperationSeek();
441
442 LttngLocation curLocation = new LttngLocation(previousLocation);
443
444 return new TmfContext(curLocation);
445 }
446
447 /**
448 * Position the trace to the event at the given position (rank).
449 * <p>
450 * NOTE : Seeking by position is very slow in LTTng, consider seeking by timestamp.
451 *
452 * @param position
453 * Position (or rank) of the event in the trace, starting at 0.
454 *
455 * @return The TmfContext that point to this event
456 *
457 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
458 * @see org.eclipse.linuxtools.tmf.trace.TmfContext
459 */
460 @Override
461 public synchronized TmfContext seekEvent(long position) {
462
463 if (PrintDebug) {
464 System.out.println("seekEvent(position) position -> " + position); //$NON-NLS-1$
465 }
466
467 TmfTimestamp timestamp = null;
468 long index = position / getCacheSize();
469
470 // Get the timestamp of the closest check point to the given position
471 if (fCheckpoints.size() > 0) {
472 if (index >= fCheckpoints.size()) {
473 index = fCheckpoints.size() - 1;
474 }
475 timestamp = fCheckpoints.elementAt((int) index).getTimestamp();
476 }
477 // If none, take the start time of the trace
478 else {
479 timestamp = getStartTime();
480 }
481
482 // Seek to the found time
483 TmfContext tmpContext = seekEvent(timestamp);
484 tmpContext.setRank((index + 1) * fIndexPageSize);
485 previousLocation = (LttngLocation) tmpContext.getLocation();
486
487 // Ajust the index of the event we found at this check point position
488 Long currentPosition = index * getCacheSize();
489
490 Long lastTimeValueRead = 0L;
491
492 // Get the event at current position. This won't move to the next one
493 JniEvent tmpJniEvent = currentJniTrace.findNextEvent();
494 // Now that we are positionned at the checkpoint,
495 // we need to "readNext" (Position - CheckpointPosition) times or until
496 // trace "run out"
497 while ((tmpJniEvent != null) && (currentPosition < position)) {
498 tmpJniEvent = currentJniTrace.readNextEvent();
499 currentPosition++;
500 }
501
502 // If we found our event, save its timestamp
503 if (tmpJniEvent != null) {
504 lastTimeValueRead = tmpJniEvent.getEventTime().getTime();
505 }
506
507 // Set the operation marker as seek, to be able to detect we did "seek"
508 // this event
509 previousLocation.setLastOperationSeek();
510 // Save read event time
511 previousLocation.setOperationTime(lastTimeValueRead);
512
513 // *** VERIFY ***
514 // Is that too paranoid?
515 //
516 // We don't trust what upper level could do with our internal location
517 // so we create a new one to return instead
518 LttngLocation curLocation = new LttngLocation(previousLocation);
519
520 return new TmfContext(curLocation);
521 }
522
523 @Override
524 public TmfContext seekLocation(double ratio) {
525 // TODO Auto-generated method stub
526 return null;
527 }
528
529 @Override
530 public double getLocationRatio(ITmfLocation<?> location) {
531 // TODO Auto-generated method stub
532 return 0;
533 }
534
535 /**
536 * Return the event in the trace according to the given context. Read it if necessary.
537 * <p>
538 * Similar (same?) as ParseEvent except that calling GetNext twice read the next one the second time.
539 *
540 * @param context
541 * Current TmfContext where to get the event
542 *
543 * @return The LttngEvent we read of null if no event are available
544 *
545 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
546 * @see org.eclipse.linuxtools.tmf.trace.TmfContext
547 */
548
549 public int nbEventsRead = 0;
550
551 @Override
552 public synchronized LttngEvent getNextEvent(TmfContext context) {
553
554 if (PrintDebug) {
555 System.out.println("getNextEvent(context) context.getLocation() -> " //$NON-NLS-1$
556 + context.getLocation());
557 }
558
559 LttngEvent returnedEvent = null;
560 LttngLocation curLocation = null;
561
562 curLocation = (LttngLocation) context.getLocation();
563 // If the location in context is null, create a new one
564 if (curLocation == null) {
565 curLocation = getCurrentLocation(context);
566 }
567
568 // *** Positioning trick :
569 // GetNextEvent only read the trace if :
570 // 1- The last operation was NOT a ParseEvent --> A read is required
571 // OR
572 // 2- The time of the previous location is different from the current
573 // one --> A seek + a read is required
574 if ((!(curLocation.isLastOperationParse()))
575 || (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue())) {
576 if (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue()) {
577 if (PrintDebug) {
578 System.out.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
579 + previousLocation.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
580 + curLocation.getOperationTimeValue() + " ]"); //$NON-NLS-1$
581 }
582 seekEvent(curLocation.getOperationTime());
583 }
584 // Read the next event from the trace. The last one will NO LONGER
585 // BE VALID.
586 returnedEvent = readNextEvent(curLocation);
587
588 } else {
589 // No event was read, just return the one currently loaded (the last
590 // one we read)
591 returnedEvent = currentLttngEvent;
592
593 // *** IMPORTANT!
594 // Reset (erase) the operation marker to both location, to be able
595 // to detect we did NOT "read" this event
596 previousLocation.resetLocationState();
597 curLocation.resetLocationState();
598 }
599
600 // If we read an event, set it's time to the locations (both previous
601 // and current)
602 if (returnedEvent != null) {
603 setPreviousAndCurrentTimes(context, returnedEvent, curLocation);
604 }
605
606 return returnedEvent;
607 }
608
609 // this method was extracted for profiling purposes
610 private void setPreviousAndCurrentTimes(TmfContext context, LttngEvent returnedEvent, LttngLocation curLocation) {
611
612 TmfTimestamp eventTimestamp = returnedEvent.getTimestamp();
613 // long eventTime = eventTimestamp.getValue();
614 previousLocation.setOperationTime(eventTimestamp.getValue());
615 curLocation.setOperationTime(eventTimestamp.getValue());
616 updateIndex(context, context.getRank(), eventTimestamp);
617 context.updateRank(1);
618 }
619
620 protected void updateIndex(TmfContext context, long rank, TmfTimestamp timestamp) {
621
622 if (getStartTime().compareTo(timestamp, false) > 0)
623 setStartTime(timestamp);
624 if (getEndTime().compareTo(timestamp, false) < 0)
625 setEndTime(timestamp);
626 if (rank != ITmfContext.UNKNOWN_RANK) {
627 if (fNbEvents <= rank)
628 fNbEvents = rank + 1;
629 // Build the index as we go along
630 if ((rank % fIndexPageSize) == 0) {
631 // Determine the table position
632 long position = rank / fIndexPageSize;
633 // Add new entry at proper location (if empty)
634 if (fCheckpoints.size() == position) {
635 addCheckPoint(context, timestamp);
636 }
637 }
638 }
639 }
640
641 private void addCheckPoint(TmfContext context, TmfTimestamp timestamp) {
642 ITmfLocation<?> location = context.getLocation().clone();
643 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
644 }
645
646 // this method was extracted for profiling purposes
647 private LttngEvent readNextEvent(LttngLocation curLocation) {
648 LttngEvent returnedEvent;
649 // Read the next event from the trace. The last one will NO LONGER BE
650 // VALID.
651 returnedEvent = readEvent(curLocation);
652 nbEventsRead++;
653
654 // Set the operation marker as read to both location, to be able to
655 // detect we did "read" this event
656 previousLocation.setLastOperationReadNext();
657 curLocation.setLastOperationReadNext();
658 return returnedEvent;
659 }
660
661 // this method was extracted for profiling purposes
662 private LttngLocation getCurrentLocation(TmfContext context) {
663 LttngLocation curLocation;
664 curLocation = new LttngLocation();
665 context.setLocation(curLocation);
666 return curLocation;
667 }
668
669 /**
670 * Return the event in the trace according to the given context. Read it if necessary.
671 * <p>
672 * Similar (same?) as GetNextEvent except that calling ParseEvent twice will return the same event
673 *
674 * @param context
675 * Current TmfContext where to get the event
676 *
677 * @return The LttngEvent we read of null if no event are available
678 *
679 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
680 * @see org.eclipse.linuxtools.tmf.trace.TmfContext
681 */
682 @Override
683 public synchronized LttngEvent parseEvent(TmfContext context) {
684
685 if (PrintDebug) {
686 System.out.println("parseEvent(context) context.getLocation() -> " //$NON-NLS-1$
687 + context.getLocation());
688 }
689
690 LttngEvent returnedEvent = null;
691 LttngLocation curLocation = null;
692
693 // If the location in context is null, create a new one
694 if (context.getLocation() == null) {
695 curLocation = new LttngLocation();
696 context.setLocation(curLocation);
697 }
698 // Otherwise, we use the one in context; it should be a valid
699 // LttngLocation
700 else {
701 curLocation = (LttngLocation) context.getLocation();
702 }
703
704 // *** HACK ***
705 // TMF assumes it is possible to read (GetNextEvent) to the next Event
706 // once ParseEvent() is called
707 // In LTTNG, there is not difference between "Parsing" and "Reading" an
708 // event.
709 // So, before "Parsing" an event, we have to make sure we didn't "Read"
710 // it alreafy.
711 // Also, "Reading" invalidate the previous Event in LTTNG and seek back
712 // is very costly,
713 // so calling twice "Parse" will return the same event, giving a way to
714 // get the "Currently loaded" event
715
716 // *** Positionning trick :
717 // ParseEvent only read the trace if :
718 // 1- The last operation was NOT a ParseEvent or a GetNextEvent --> A
719 // read is required
720 // OR
721 // 2- The time of the previous location is different from the current
722 // one --> A seek + a read is required
723 if (((!(curLocation.isLastOperationParse())) && ((!(curLocation.isLastOperationReadNext()))))
724 || (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue())) {
725 // Previous time != Current time : We need to reposition to the
726 // current time
727 if (previousLocation.getOperationTimeValue() != curLocation.getOperationTimeValue()) {
728 if (PrintDebug) {
729 System.out.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
730 + previousLocation.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
731 + curLocation.getOperationTimeValue() + " ]"); //$NON-NLS-1$
732 }
733 seekEvent(curLocation.getOperationTime());
734 }
735
736 // Read the next event from the trace. The last one will NO LONGER
737 // BE VALID.
738 returnedEvent = readEvent(curLocation);
739 } else {
740 // No event was read, just return the one currently loaded (the last
741 // one we read)
742 returnedEvent = currentLttngEvent;
743 }
744
745 // If we read an event, set it's time to the locations (both previous
746 // and current)
747 if (returnedEvent != null) {
748 previousLocation.setOperationTime((LttngTimestamp) returnedEvent.getTimestamp());
749 curLocation.setOperationTime((LttngTimestamp) returnedEvent.getTimestamp());
750 }
751
752 // Set the operation marker as parse to both location, to be able to
753 // detect we already "read" this event
754 previousLocation.setLastOperationParse();
755 curLocation.setLastOperationParse();
756
757 return returnedEvent;
758 }
759
760 /*
761 * Read the next event from the JNI and convert it as Lttng Event<p>
762 *
763 * @param location Current LttngLocation that to be updated with the event timestamp
764 *
765 * @return The LttngEvent we read of null if no event are available
766 *
767 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
768 *
769 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
770 */
771 private synchronized LttngEvent readEvent(LttngLocation location) {
772 LttngEvent returnedEvent = null;
773 JniEvent tmpEvent = null;
774
775 // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG
776 // EVENT.
777 tmpEvent = currentJniTrace.readNextEvent();
778
779 if (tmpEvent != null) {
780 // *** NOTE
781 // Convert will update the currentLttngEvent
782 returnedEvent = convertJniEventToTmf(tmpEvent);
783
784 location.setOperationTime((LttngTimestamp) returnedEvent.getTimestamp());
785 }
786 // *** NOTE
787 // If the read failed (likely the last event in the trace), set the
788 // LastReadTime to the JNI time
789 // That way, even if we try to read again, we will step over the bogus
790 // seek and read
791 else {
792 location.setOperationTime(getEndTime().getValue() + 1);
793 }
794
795 return returnedEvent;
796 }
797
798 /**
799 * Method to convert a JniEvent into a LttngEvent.
800 * <p>
801 *
802 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent, boolean) with a default value for
803 * isParsingNeeded
804 *
805 * @param newEvent
806 * The JniEvent to convert into LttngEvent
807 *
808 * @return The converted LttngEvent
809 *
810 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
811 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
812 */
813 public synchronized LttngEvent convertJniEventToTmf(JniEvent newEvent) {
814 currentLttngEvent = convertJniEventToTmf(newEvent, IS_PARSING_NEEDED_DEFAULT);
815
816 return currentLttngEvent;
817 }
818
819 /**
820 * Method to convert a JniEvent into a LttngEvent
821 *
822 * @param jniEvent
823 * The JniEvent to convert into LttngEvent
824 * @param isParsingNeeded
825 * A boolean value telling if the event should be parsed or not.
826 *
827 * @return The converted LttngEvent
828 *
829 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
830 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
831 */
832 public synchronized LttngEvent convertJniEventToTmf(JniEvent jniEvent, boolean isParsingNeeded) {
833
834 if (UniqueEvent) {
835
836 // ***
837 // UNHACKED : We can no longer do that because TCF need to maintain
838 // several events at once.
839 // This is very slow to do so in LTTng, this has to be temporary.
840 // *** HACK ***
841 // To save time here, we only set value instead of allocating new
842 // object
843 // This give an HUGE performance improvement
844 // all allocation done in the LttngTrace constructor
845 // ***
846 eventTimestamp.setValue(jniEvent.getEventTime().getTime());
847 eventSource.setSourceId(jniEvent.requestEventSource());
848
849 eventType = traceTypes.get(EventTypeKey.getEventTypeHash(jniEvent));
850
851 eventReference.setValue(jniEvent.getParentTracefile().getTracefilePath());
852 eventReference.setTracepath(this.getName());
853
854 eventContent.emptyContent();
855
856 currentLttngEvent.setType(eventType);
857 // Save the jni reference
858 currentLttngEvent.updateJniEventReference(jniEvent);
859
860 // Parse now if was asked
861 // Warning : THIS IS SLOW
862 if (isParsingNeeded) {
863 eventContent.getFields();
864 }
865
866 return currentLttngEvent;
867 } else {
868 return convertJniEventToTmfMultipleEventEvilFix(jniEvent, isParsingNeeded);
869 }
870
871 }
872
873 /**
874 * This method is a temporary fix to support multiple events at once in TMF This is expected to be slow and should
875 * be fixed in another way. See comment in convertJniEventToTmf();
876 *
877 * @param jniEvent
878 * The current JNI Event
879 * @return Current Lttng Event fully parsed
880 */
881 private synchronized LttngEvent convertJniEventToTmfMultipleEventEvilFix(JniEvent jniEvent, boolean isParsingNeeded) {
882 // *** HACK ***
883 // Below : the "fix" with all the new and the full-parse
884 // Allocating new memory is slow.
885 // Parsing every events is very slow.
886 eventTimestamp = new LttngTimestamp(jniEvent.getEventTime().getTime());
887 eventSource = new LttngEventSource(jniEvent.requestEventSource());
888 eventReference = new LttngEventReference(jniEvent.getParentTracefile().getTracefilePath(), this.getName());
889 eventType = new LttngEventType(traceTypes.get(EventTypeKey.getEventTypeHash(jniEvent)));
890 eventContent = new LttngEventContent(currentLttngEvent);
891 currentLttngEvent = new LttngEvent(this, eventTimestamp, eventSource, eventType, eventContent, eventReference,
892 null);
893
894 // The jni reference is no longer reliable but we will keep it anyhow
895 currentLttngEvent.updateJniEventReference(jniEvent);
896 // Ensure that the content is correctly set
897 eventContent.setEvent(currentLttngEvent);
898
899 // Parse the event if it was needed
900 // *** WARNING ***
901 // ONLY for testing, NOT parsing events with non-unique events WILL
902 // result in segfault in the JVM
903 if (isParsingNeeded) {
904 eventContent.getFields();
905 }
906
907 return currentLttngEvent;
908 }
909
910 /**
911 * Reference to the current LttngTrace we are reading from.
912 * <p>
913 *
914 * Note : This bypass the framework and should not be use, except for testing!
915 *
916 * @return Reference to the current LttngTrace
917 *
918 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
919 */
920 public JniTrace getCurrentJniTrace() {
921 return currentJniTrace;
922 }
923
924 /**
925 * Return a reference to the current LttngEvent we have in memory.
926 *
927 * @return The current (last read) LttngEvent
928 *
929 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
930 */
931 public synchronized LttngEvent getCurrentEvent() {
932 return currentLttngEvent;
933 }
934
935 /**
936 * Get the major version number for the current trace
937 *
938 * @return Version major or -1 if unknown
939 *
940 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
941 *
942 */
943 public short getVersionMajor() {
944 if (currentJniTrace != null) {
945 return currentJniTrace.getLttMajorVersion();
946 } else {
947 return -1;
948 }
949 }
950
951 /**
952 * Get the minor version number for the current trace
953 *
954 * @return Version minor or -1 if unknown
955 *
956 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
957 *
958 */
959 public short getVersionMinor() {
960 if (currentJniTrace != null) {
961 return currentJniTrace.getLttMinorVersion();
962 } else {
963 return -1;
964 }
965 }
966
967 /**
968 * Get the number of CPU for this trace
969 *
970 * @return Number of CPU or -1 if unknown
971 *
972 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
973 *
974 */
975 public int getCpuNumber() {
976 if (currentJniTrace != null) {
977 return currentJniTrace.getCpuNumber();
978 } else {
979 return -1;
980 }
981 }
982
983 /**
984 * Print the content of the checkpoint vector.
985 * <p>
986 *
987 * This is intended for debug purpose only.
988 */
989 public void printCheckpointsVector() {
990 System.out.println("StartTime : " //$NON-NLS-1$
991 + getTimeRange().getStartTime().getValue());
992 System.out.println("EndTime : " //$NON-NLS-1$
993 + getTimeRange().getEndTime().getValue());
994
995 for (int pos = 0; pos < fCheckpoints.size(); pos++) {
996 System.out.print(pos + ": " + "\t"); //$NON-NLS-1$ //$NON-NLS-2$
997 System.out.print(fCheckpoints.get(pos).getTimestamp() + "\t"); //$NON-NLS-1$
998 System.out.println(fCheckpoints.get(pos).getLocation());
999 }
1000 }
1001
1002 @Override
1003 public synchronized void dispose() {
1004 if (currentJniTrace != null)
1005 currentJniTrace.closeTrace();
1006 super.dispose();
1007 }
1008
1009 /**
1010 * Return a String identifying this trace.
1011 *
1012 * @return String that identify this trace
1013 */
1014 @Override
1015 @SuppressWarnings("nls")
1016 public String toString() {
1017 String returnedData = "";
1018
1019 returnedData += "Path :" + getPath() + " ";
1020 returnedData += "Trace:" + currentJniTrace + " ";
1021 returnedData += "Event:" + currentLttngEvent;
1022
1023 return returnedData;
1024 }
1025
1026 }
1027
1028 /*
1029 * EventTypeKey inner class
1030 *
1031 * This class is used to make the process of generating the HashMap key more transparent and so less error prone to use
1032 */
1033 final class EventTypeKey {
1034 // *** WARNING ***
1035 // These two getEventTypeKey() functions should ALWAYS construct the key the
1036 // same ways!
1037 // Otherwise, every type search will fail!
1038
1039 // added final to encourage inlining.
1040
1041 // generating a hash code by hand to avoid a string creation
1042 final static public int getEventTypeHash(LttngEventType newEventType) {
1043 return generateHash(newEventType.getTracefileName(), newEventType.getCpuId(), newEventType.getMarkerName());
1044 }
1045
1046 final private static int generateHash(String traceFileName, long cpuNumber, String markerName) {
1047 // 0x1337 is a prime number. The number of CPUs is always under 8192 on
1048 // the current kernel, so this will work with the current linux kernel.
1049 int cpuHash = (int) (cpuNumber * (0x1337));
1050 return traceFileName.hashCode() ^ (cpuHash) ^ markerName.hashCode();
1051 }
1052
1053 // generating a hash code by hand to avoid a string creation
1054 final static public int getEventTypeHash(JniEvent newEvent) {
1055 return generateHash(newEvent.getParentTracefile().getTracefileName(), newEvent.getParentTracefile()
1056 .getCpuNumber(), newEvent.requestEventMarker().getName());
1057 }
1058
1059 }
This page took 0.053822 seconds and 5 git commands to generate.