1 /*******************************************************************************
2 * Copyright (c) 2009, 2011 Ericsson, MontaVista Software
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
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 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.internal
.lttng
.core
.trace
;
16 import java
.io
.FileNotFoundException
;
17 import java
.util
.HashMap
;
18 import java
.util
.Iterator
;
19 import java
.util
.Vector
;
21 import org
.eclipse
.core
.resources
.IProject
;
22 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.TraceHelper
;
23 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEvent
;
24 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventContent
;
25 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventType
;
26 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngLocation
;
27 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngTimestamp
;
28 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.exceptions
.LttngException
;
29 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.tracecontrol
.utility
.LiveTraceManager
;
30 import org
.eclipse
.linuxtools
.internal
.lttng
.jni
.common
.JniTime
;
31 import org
.eclipse
.linuxtools
.internal
.lttng
.jni
.exception
.JniException
;
32 import org
.eclipse
.linuxtools
.lttng
.jni
.JniEvent
;
33 import org
.eclipse
.linuxtools
.lttng
.jni
.JniMarker
;
34 import org
.eclipse
.linuxtools
.lttng
.jni
.JniTrace
;
35 import org
.eclipse
.linuxtools
.lttng
.jni
.JniTracefile
;
36 import org
.eclipse
.linuxtools
.lttng
.jni
.factory
.JniTraceFactory
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEvent
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.experiment
.TmfExperiment
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
.ExecutionType
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfEventRequest
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceUpdatedSignal
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
50 class LTTngTraceException
extends LttngException
{
52 static final long serialVersionUID
= -1636648737081868146L;
54 public LTTngTraceException(final String errMsg
) {
60 * <b><u>LTTngTrace</u></b>
63 * LTTng trace implementation. It accesses the C trace handling library
64 * (seeking, reading and parsing) through the JNI component.
66 public class LTTngTrace
extends TmfTrace
<LttngEvent
> {
68 public final static boolean PRINT_DEBUG
= false;
69 public final static boolean UNIQUE_EVENT
= true;
71 private final static boolean SHOW_LTT_DEBUG_DEFAULT
= false;
72 private final static boolean IS_PARSING_NEEDED_DEFAULT
= !UNIQUE_EVENT
;
73 private final static int CHECKPOINT_PAGE_SIZE
= 50000;
74 private final static long LTTNG_STREAMING_INTERVAL
= 2000; // in ms
76 // Reference to our JNI trace
77 private JniTrace currentJniTrace
;
79 LttngTimestamp eventTimestamp
;
81 LttngEventContent eventContent
;
82 String eventReference
;
85 LttngEvent currentLttngEvent
;
87 // The current location
88 LttngLocation previousLocation
;
90 LttngEventType eventType
;
92 // Hashmap of the possible types of events (Tracefile/CPU/Marker in the JNI)
93 HashMap
<Integer
, LttngEventType
> traceTypes
;
95 // This vector will be used to quickly find a marker name from a position
96 Vector
<Integer
> traceTypeNames
;
98 private String traceLibPath
;
100 public LTTngTrace() {
104 public boolean validate(final IProject project
, final String path
) {
105 if (super.validate(project
, path
)) {
106 final String traceLibPath
= TraceHelper
.getTraceLibDirFromProject(project
);
108 final LTTngTraceVersion version
= new LTTngTraceVersion(path
, traceLibPath
);
109 return version
.isValidLttngTrace();
110 } catch (final LttngException e
) {
117 public synchronized void initTrace(final String name
, final String path
, final Class
<LttngEvent
> eventType
)
118 throws FileNotFoundException
{
119 super.initTrace(name
, path
, eventType
);
121 currentJniTrace
= JniTraceFactory
.getJniTrace(path
, traceLibPath
, SHOW_LTT_DEBUG_DEFAULT
);
122 } catch (final Exception e
) {
123 throw new FileNotFoundException(e
.getMessage());
126 // Export all the event types from the JNI side
127 traceTypes
= new HashMap
<Integer
, LttngEventType
>();
128 traceTypeNames
= new Vector
<Integer
>();
129 initialiseEventTypes(currentJniTrace
);
131 // Build the re-used event structure
132 eventTimestamp
= new LttngTimestamp();
133 eventSource
= ""; //$NON-NLS-1$
134 this.eventType
= new LttngEventType();
135 eventContent
= new LttngEventContent(currentLttngEvent
);
136 eventReference
= getName();
138 // Create the skeleton event
139 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, this.eventType
, eventContent
,
140 eventReference
, null);
142 // Create a new current location
143 previousLocation
= new LttngLocation();
145 // Set the currentEvent to the eventContent
146 eventContent
.setEvent(currentLttngEvent
);
148 // // Bypass indexing if asked
149 // if ( bypassIndexing == false ) {
153 // Even if we don't have any index, set ONE checkpoint
154 // fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L) , new
155 // LttngLocation() ) );
157 initializeStreamingMonitor();
160 private void initializeStreamingMonitor() {
161 final JniTrace jniTrace
= getCurrentJniTrace();
163 || (!jniTrace
.isLiveTraceSupported() || !LiveTraceManager
.isLiveTrace(jniTrace
.getTracepath()))) {
164 // Set the time range of the trace
165 final TmfContext context
= seekLocation(null);
166 final LttngEvent event
= getNextEvent(context
);
167 final LttngTimestamp startTime
= new LttngTimestamp(event
.getTimestamp());
168 final LttngTimestamp endTime
= new LttngTimestamp(currentJniTrace
.getEndTime().getTime());
169 setTimeRange(new TmfTimeRange(startTime
, endTime
));
170 final TmfTraceUpdatedSignal signal
= new TmfTraceUpdatedSignal(this, this, getTimeRange());
175 // Set the time range of the trace
176 final TmfContext context
= seekLocation(null);
177 final LttngEvent event
= getNextEvent(context
);
178 setEndTime(TmfTimestamp
.BIG_BANG
);
179 final long startTime
= event
!= null ? event
.getTimestamp().getValue() : TmfTimestamp
.BIG_BANG
.getValue();
180 fStreamingInterval
= LTTNG_STREAMING_INTERVAL
;
182 final Thread thread
= new Thread("Streaming Monitor for trace " + getName()) { //$NON-NLS-1$
184 LttngTimestamp safeTimestamp
= null;
185 TmfTimeRange timeRange
= null;
187 @SuppressWarnings("unchecked")
190 while (!fExecutor
.isShutdown()) {
191 final TmfExperiment
<?
> experiment
= TmfExperiment
.getCurrentExperiment();
192 if (experiment
!= null) {
193 @SuppressWarnings("rawtypes")
194 final TmfEventRequest request
= new TmfEventRequest
<TmfEvent
>(TmfEvent
.class,
195 TmfTimeRange
.ETERNITY
, 0, ExecutionType
.FOREGROUND
) {
198 public void handleCompleted() {
202 synchronized (experiment
) {
203 experiment
.sendRequest(request
);
206 request
.waitForCompletion();
207 } catch (final InterruptedException e
) {
213 Thread
.sleep(LTTNG_STREAMING_INTERVAL
);
214 } catch (final InterruptedException e
) {
220 private void updateJniTrace() {
221 final JniTrace jniTrace
= getCurrentJniTrace();
222 currentJniTrace
.updateTrace();
223 final long endTime
= jniTrace
.getEndTime().getTime();
224 final LttngTimestamp startTimestamp
= new LttngTimestamp(startTime
);
225 final LttngTimestamp endTimestamp
= new LttngTimestamp(endTime
);
226 if (safeTimestamp
!= null && safeTimestamp
.compareTo(getTimeRange().getEndTime(), false) > 0)
227 timeRange
= new TmfTimeRange(startTimestamp
, safeTimestamp
);
230 safeTimestamp
= endTimestamp
;
231 if (timeRange
!= null)
232 setTimeRange(timeRange
);
239 * Default Constructor.
242 * @param name Name of the trace
243 * @param path Path to a <b>directory</b> that contain an LTTng trace.
245 * @exception Exception (most likely LTTngTraceException or
246 * FileNotFoundException)
248 public LTTngTrace(final String name
, final String path
) throws Exception
{
249 // Call with "wait for completion" true and "skip indexing" false
250 this(name
, path
, null, true, false);
254 * Constructor, with control over the indexing.
257 * @param name Name of the trace
258 * @param path Path to a <b>directory</b> that contain an LTTng trace.
259 * @param waitForCompletion Should we wait for indexign to complete before
262 * @exception Exception (most likely LTTngTraceException or
263 * FileNotFoundException)
265 public LTTngTrace(final String name
, final String path
, final boolean waitForCompletion
) throws Exception
{
266 // Call with "skip indexing" false
267 this(name
, path
, null, waitForCompletion
, true);
271 * Default constructor, with control over the indexing and possibility to
275 * @param name Name of the trace
276 * @param path Path to a <b>directory</b> that contain an LTTng trace.
277 * @param traceLibPath Path to a <b>directory</b> that contains LTTng trace
279 * @param waitForCompletion Should we wait for indexign to complete before
281 * @param bypassIndexing Should we bypass indexing completly? This is should
282 * only be useful for unit testing.
284 * @exception Exception (most likely LTTngTraceException or
285 * FileNotFoundException)
288 public LTTngTrace(final String name
, final String path
, final String traceLibPath
, final boolean waitForCompletion
,
289 final boolean bypassIndexing
)
291 super(name
, LttngEvent
.class, path
, CHECKPOINT_PAGE_SIZE
, false);
292 initTrace(name
, path
, LttngEvent
.class);
295 this.traceLibPath
= traceLibPath
;
299 * Copy constructor is forbidden for LttngEvenmStream
301 public LTTngTrace(final LTTngTrace other
) throws Exception
{
302 this(other
.getName(), other
.getPath(), other
.getTraceLibPath(), false, true);
303 this.fCheckpoints
= other
.fCheckpoints
;
304 setTimeRange(new TmfTimeRange(new LttngTimestamp(other
.getStartTime()), new LttngTimestamp(other
.getEndTime())));
308 public synchronized LTTngTrace
clone() {
309 LTTngTrace clone
= null;
310 clone
= (LTTngTrace
) super.clone();
312 clone
.currentJniTrace
= JniTraceFactory
.getJniTrace(getPath(), getTraceLibPath(),
313 SHOW_LTT_DEBUG_DEFAULT
);
314 } catch (final JniException e
) {
315 // e.printStackTrace();
318 // Export all the event types from the JNI side
319 clone
.traceTypes
= new HashMap
<Integer
, LttngEventType
>();
320 clone
.traceTypeNames
= new Vector
<Integer
>();
321 clone
.initialiseEventTypes(clone
.currentJniTrace
);
323 // Verify that all those "default constructor" are safe to use
324 clone
.eventTimestamp
= new LttngTimestamp();
325 clone
.eventSource
= ""; //$NON-NLS-1$
326 clone
.eventType
= new LttngEventType();
327 clone
.eventContent
= new LttngEventContent(clone
.currentLttngEvent
);
328 clone
.eventReference
= getName();
330 // Create the skeleton event
331 clone
.currentLttngEvent
= new LttngEvent(this, clone
.eventTimestamp
, clone
.eventSource
, clone
.eventType
,
332 clone
.eventContent
, clone
.eventReference
, null);
334 // Create a new current location
335 clone
.previousLocation
= new LttngLocation();
337 // Set the currentEvent to the eventContent
338 clone
.eventContent
.setEvent(clone
.currentLttngEvent
);
340 // Set the start time of the trace
341 setTimeRange(new TmfTimeRange(new LttngTimestamp(clone
.currentJniTrace
.getStartTime().getTime()),
342 new LttngTimestamp(clone
.currentJniTrace
.getEndTime().getTime())));
347 public String
getTraceLibPath() {
352 * Fill out the HashMap with "Type" (Tracefile/Marker)
354 * This should be called at construction once the trace is open
356 private void initialiseEventTypes(final JniTrace trace
) {
358 LttngEventType tmpType
= null;
359 String
[] markerFieldsLabels
= null;
361 String newTracefileKey
= null;
362 Integer newMarkerKey
= null;
364 JniTracefile newTracefile
= null;
365 JniMarker newMarker
= null;
367 // First, obtain an iterator on TRACEFILES of owned by the TRACE
368 final Iterator
<String
> tracefileItr
= trace
.getTracefilesMap().keySet().iterator();
370 while (tracefileItr
.hasNext()) {
371 newTracefileKey
= tracefileItr
.next();
372 newTracefile
= trace
.getTracefilesMap().get(newTracefileKey
);
374 // From the TRACEFILE read, obtain its MARKER
375 final Iterator
<Integer
> markerItr
= newTracefile
.getTracefileMarkersMap().keySet().iterator();
376 while (markerItr
.hasNext()) {
377 newMarkerKey
= markerItr
.next();
378 newMarker
= newTracefile
.getTracefileMarkersMap().get(newMarkerKey
);
380 // From the MARKER we can obtain the MARKERFIELDS keys (i.e.
382 markerFieldsLabels
= newMarker
.getMarkerFieldsHashMap().keySet()
383 .toArray(new String
[newMarker
.getMarkerFieldsHashMap().size()]);
385 tmpType
= new LttngEventType(newTracefile
.getTracefileName(), newTracefile
.getCpuNumber(),
386 newMarker
.getName(), newMarkerKey
.intValue(), markerFieldsLabels
);
388 // Add the type to the map/vector
389 addEventTypeToMap(tmpType
);
395 * Add a new type to the HashMap
397 * As the hashmap use a key format that is a bit dangerous to use, we should
398 * always add using this function.
400 private void addEventTypeToMap(final LttngEventType newEventType
) {
401 final int newTypeKey
= EventTypeKey
.getEventTypeHash(newEventType
);
403 this.traceTypes
.put(newTypeKey
, newEventType
);
404 this.traceTypeNames
.add(newTypeKey
);
408 * Return the latest saved location. Note : Modifying the returned location
409 * may result in buggy positionning!
411 * @return The LttngLocation as it was after the last operation.
413 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
416 public synchronized ITmfLocation
<?
> getCurrentLocation() {
417 return previousLocation
;
421 * Position the trace to the event at the given location.
423 * NOTE : Seeking by location is very fast compare to seeking by position
424 * but is still slower than "ReadNext", avoid using it for small interval.
426 * @param location Location of the event in the trace. If no event available
427 * at this exact location, we will position ourself to the next
430 * @return The TmfContext that point to this event
432 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
433 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
436 public synchronized TmfContext
seekLocation(final ITmfLocation
<?
> location
) {
442 System
.out
.println("seekLocation(location) location -> " + location
); //$NON-NLS-1$
444 // If the location in context is null, create a new one
445 LttngLocation curLocation
= null;
446 if (location
== null) {
447 curLocation
= new LttngLocation();
448 final TmfContext context
= seekEvent(curLocation
.getOperationTime());
449 context
.setRank(ITmfContext
.INITIAL_RANK
);
452 curLocation
= (LttngLocation
) location
;
455 // Update to location should (and will) be done in SeekEvent.
457 // The only seek valid in LTTng is with the time, we call
458 // seekEvent(timestamp)
459 final TmfContext context
= seekEvent(curLocation
.getOperationTime());
461 // If the location is marked with the read next flag
462 // then it is pointing to the next event following the operation time
463 if (curLocation
.isLastOperationReadNext())
464 getNextEvent(context
);
470 * Position the trace to the event at the given time.
472 * NOTE : Seeking by time is very fast compare to seeking by position but is
473 * still slower than "ReadNext", avoid using it for small interval.
475 * @param timestamp Time of the event in the trace. If no event available at
476 * this exact time, we will position ourself to the next one.
478 * @return The TmfContext that point to this event
480 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
481 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
484 public synchronized TmfContext
seekEvent(final ITmfTimestamp timestamp
) {
487 System
.out
.println("seekEvent(timestamp) timestamp -> " + timestamp
); //$NON-NLS-1$
490 currentJniTrace
.seekToTime(new JniTime(timestamp
.getValue()));
492 // Save the time at which we seeked
493 previousLocation
.setOperationTime(timestamp
.getValue());
494 // Set the operation marker as seek, to be able to detect we did "seek"
496 previousLocation
.setLastOperationSeek();
498 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
500 return new TmfContext(curLocation
);
504 * Position the trace to the event at the given position (rank).
506 * NOTE : Seeking by position is very slow in LTTng, consider seeking by
509 * @param rank Position (or rank) of the event in the trace, starting at 0.
511 * @return The TmfContext that point to this event
513 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
514 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
517 public synchronized TmfContext
seekEvent(final long rank
) {
520 System
.out
.println("seekEvent(rank) rank -> " + rank
); //$NON-NLS-1$
522 ITmfTimestamp timestamp
= null;
523 long index
= rank
/ getIndexPageSize();
525 // Get the timestamp of the closest check point to the given position
526 if (fCheckpoints
.size() > 0) {
527 if (index
>= fCheckpoints
.size())
528 index
= fCheckpoints
.size() - 1;
529 timestamp
= fCheckpoints
.elementAt((int) index
).getTimestamp();
531 timestamp
= getStartTime();
533 // Seek to the found time
534 final TmfContext tmpContext
= seekEvent(timestamp
);
535 tmpContext
.setRank((index
+ 1) * fIndexPageSize
);
536 previousLocation
= (LttngLocation
) tmpContext
.getLocation();
538 // Ajust the index of the event we found at this check point position
539 Long currentPosition
= index
* getIndexPageSize();
541 Long lastTimeValueRead
= 0L;
543 // Get the event at current position. This won't move to the next one
544 JniEvent tmpJniEvent
= currentJniTrace
.findNextEvent();
545 // Now that we are positionned at the checkpoint,
546 // we need to "readNext" (Position - CheckpointPosition) times or until
548 while ((tmpJniEvent
!= null) && (currentPosition
< rank
)) {
549 tmpJniEvent
= currentJniTrace
.readNextEvent();
553 // If we found our event, save its timestamp
554 if (tmpJniEvent
!= null)
555 lastTimeValueRead
= tmpJniEvent
.getEventTime().getTime();
557 // Set the operation marker as seek, to be able to detect we did "seek"
559 previousLocation
.setLastOperationSeek();
560 // Save read event time
561 previousLocation
.setOperationTime(lastTimeValueRead
);
564 // Is that too paranoid?
566 // We don't trust what upper level could do with our internal location
567 // so we create a new one to return instead
568 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
570 return new TmfContext(curLocation
, rank
);
574 public TmfContext
seekLocation(final double ratio
) {
575 // TODO Auto-generated method stub
580 public double getLocationRatio(final ITmfLocation
<?
> location
) {
581 // TODO Auto-generated method stub
586 * Return the event in the trace according to the given context. Read it if
589 * Similar (same?) as ParseEvent except that calling GetNext twice read the
590 * next one the second time.
592 * @param context Current TmfContext where to get the event
594 * @return The LttngEvent we read of null if no event are available
596 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
597 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
600 public int nbEventsRead
= 0;
603 public synchronized LttngEvent
getNextEvent(final ITmfContext context
) {
606 System
.out
.println("getNextEvent(context) context.getLocation() -> " //$NON-NLS-1$
607 + context
.getLocation());
609 LttngEvent returnedEvent
= null;
610 LttngLocation curLocation
= null;
612 curLocation
= (LttngLocation
) context
.getLocation();
613 // If the location in context is null, create a new one
614 if (curLocation
== null)
615 curLocation
= getCurrentLocation(context
);
617 // *** Positioning trick :
618 // GetNextEvent only read the trace if :
619 // 1- The last operation was NOT a ParseEvent --> A read is required
621 // 2- The time of the previous location is different from the current
622 // one --> A seek + a read is required
623 if ((!(curLocation
.isLastOperationParse()))
624 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
625 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
627 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
628 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
629 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
630 seekEvent(curLocation
.getOperationTime());
632 // Read the next event from the trace. The last one will NO LONGER
634 returnedEvent
= readNextEvent(curLocation
);
637 // No event was read, just return the one currently loaded (the last
639 returnedEvent
= currentLttngEvent
;
641 // Set the operation marker as read to both locations, to be able to
642 // detect we need to read the next event
643 previousLocation
.setLastOperationReadNext();
644 curLocation
.setLastOperationReadNext();
647 // If we read an event, set it's time to the locations (both previous
649 if (returnedEvent
!= null)
650 setPreviousAndCurrentTimes(context
, returnedEvent
, curLocation
);
652 return returnedEvent
;
655 // this method was extracted for profiling purposes
656 private synchronized void setPreviousAndCurrentTimes(final ITmfContext context
, final LttngEvent returnedEvent
,
657 final LttngLocation curLocation
) {
659 final ITmfTimestamp eventTimestamp
= returnedEvent
.getTimestamp();
660 // long eventTime = eventTimestamp.getValue();
661 previousLocation
.setOperationTime(eventTimestamp
.getValue());
662 curLocation
.setOperationTime(eventTimestamp
.getValue());
663 updateIndex(context
, context
.getRank(), eventTimestamp
);
664 context
.increaseRank();
667 // protected void updateIndex(TmfContext context, long rank, ITmfTimestamp timestamp) {
669 // if (getStartTime().compareTo(timestamp, false) > 0)
670 // setStartTime(timestamp);
671 // if (getEndTime().compareTo(timestamp, false) < 0)
672 // setEndTime(timestamp);
673 // if (rank != ITmfContext.UNKNOWN_RANK) {
674 // if (fNbEvents <= rank)
675 // fNbEvents = rank + 1;
676 // // Build the index as we go along
677 // if ((rank % fIndexPageSize) == 0) {
678 // // Determine the table position
679 // long position = rank / fIndexPageSize;
680 // // Add new entry at proper location (if empty)
681 // if (fCheckpoints.size() == position) {
682 // addCheckPoint(context, timestamp);
688 // this method was extracted for profiling purposes
689 private synchronized LttngEvent
readNextEvent(final LttngLocation curLocation
) {
690 LttngEvent returnedEvent
;
691 // Read the next event from the trace. The last one will NO LONGER BE
693 returnedEvent
= readEvent(curLocation
);
696 // Set the operation marker as read to both locations, to be able to
697 // detect we need to read the next event
698 previousLocation
.setLastOperationReadNext();
699 curLocation
.setLastOperationReadNext();
700 return returnedEvent
;
703 // this method was extracted for profiling purposes
704 private LttngLocation
getCurrentLocation(final ITmfContext context
) {
705 LttngLocation curLocation
;
706 curLocation
= new LttngLocation();
707 context
.setLocation(curLocation
);
712 * Return the event in the trace according to the given context. Read it if
715 * Similar (same?) as GetNextEvent except that calling ParseEvent twice will
716 * return the same event
718 * @param context Current TmfContext where to get the event
720 * @return The LttngEvent we read of null if no event are available
722 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
723 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
726 public synchronized LttngEvent
parseEvent(final ITmfContext context
) {
729 System
.out
.println("parseEvent(context) context.getLocation() -> " //$NON-NLS-1$
730 + context
.getLocation());
732 LttngEvent returnedEvent
= null;
733 LttngLocation curLocation
= null;
735 // If the location in context is null, create a new one
736 if (context
.getLocation() == null) {
737 curLocation
= new LttngLocation();
738 context
.setLocation(curLocation
);
740 curLocation
= (LttngLocation
) context
.getLocation();
743 // TMF assumes it is possible to read (GetNextEvent) to the next Event
744 // once ParseEvent() is called
745 // In LTTNG, there is not difference between "Parsing" and "Reading" an
747 // So, before "Parsing" an event, we have to make sure we didn't "Read"
749 // Also, "Reading" invalidate the previous Event in LTTNG and seek back
751 // so calling twice "Parse" will return the same event, giving a way to
752 // get the "Currently loaded" event
754 // *** Positionning trick :
755 // ParseEvent only read the trace if :
756 // 1- The last operation was NOT a ParseEvent --> A read is required
758 // 2- The time of the previous location is different from the current
759 // one --> A seek + a read is required
760 if (!curLocation
.isLastOperationParse()
761 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
762 // Previous time != Current time : We need to reposition to the
764 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
766 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
767 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
768 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
769 seekEvent(curLocation
.getOperationTime());
772 // Read the next event from the trace. The last one will NO LONGER
774 returnedEvent
= readEvent(curLocation
);
776 // No event was read, just return the one currently loaded (the last
778 returnedEvent
= currentLttngEvent
;
780 // If we read an event, set it's time to the locations (both previous
782 if (returnedEvent
!= null) {
783 previousLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
784 curLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
787 // Set the operation marker as parse to both location, to be able to
788 // detect we already "read" this event
789 previousLocation
.setLastOperationParse();
790 curLocation
.setLastOperationParse();
792 return returnedEvent
;
796 * Read the next event from the JNI and convert it as Lttng Event<p>
798 * @param location Current LttngLocation that to be updated with the event
801 * @return The LttngEvent we read of null if no event are available
803 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
805 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
807 private synchronized LttngEvent
readEvent(final LttngLocation location
) {
808 LttngEvent returnedEvent
= null;
809 JniEvent tmpEvent
= null;
811 // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG
813 tmpEvent
= currentJniTrace
.readNextEvent();
815 if (tmpEvent
!= null) {
817 // Convert will update the currentLttngEvent
818 returnedEvent
= convertJniEventToTmf(tmpEvent
);
820 location
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
822 location
.setOperationTime(getEndTime().getValue() + 1);
824 return returnedEvent
;
828 * Method to convert a JniEvent into a LttngEvent.
831 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent,
832 * boolean) with a default value for isParsingNeeded
834 * @param newEvent The JniEvent to convert into LttngEvent
836 * @return The converted LttngEvent
838 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
839 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
841 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent newEvent
) {
842 currentLttngEvent
= convertJniEventToTmf(newEvent
, IS_PARSING_NEEDED_DEFAULT
);
844 return currentLttngEvent
;
848 * Method to convert a JniEvent into a LttngEvent
850 * @param jniEvent The JniEvent to convert into LttngEvent
851 * @param isParsingNeeded A boolean value telling if the event should be
854 * @return The converted LttngEvent
856 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
857 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
859 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent jniEvent
, final boolean isParsingNeeded
) {
864 // UNHACKED : We can no longer do that because TCF need to maintain
865 // several events at once.
866 // This is very slow to do so in LTTng, this has to be temporary.
868 // To save time here, we only set value instead of allocating new
870 // This give an HUGE performance improvement
871 // all allocation done in the LttngTrace constructor
873 eventTimestamp
.setValue(jniEvent
.getEventTime().getTime());
874 eventSource
= jniEvent
.requestEventSource();
876 eventType
= traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
));
878 final String fullTracePath
= getName();
879 final String reference
= fullTracePath
.substring(fullTracePath
.lastIndexOf('/') + 1);
880 currentLttngEvent
.setReference(reference
);
882 eventContent
.emptyContent();
884 currentLttngEvent
.setType(eventType
);
885 // Save the jni reference
886 currentLttngEvent
.updateJniEventReference(jniEvent
);
888 // Parse now if was asked
889 // Warning : THIS IS SLOW
891 eventContent
.getFields();
893 return currentLttngEvent
;
895 return convertJniEventToTmfMultipleEventEvilFix(jniEvent
, isParsingNeeded
);
900 * This method is a temporary fix to support multiple events at once in TMF
901 * This is expected to be slow and should be fixed in another way. See
902 * comment in convertJniEventToTmf();
904 * @param jniEvent The current JNI Event
905 * @return Current Lttng Event fully parsed
907 private synchronized LttngEvent
convertJniEventToTmfMultipleEventEvilFix(final JniEvent jniEvent
,
908 final boolean isParsingNeeded
) {
910 // Below : the "fix" with all the new and the full-parse
911 // Allocating new memory is slow.
912 // Parsing every events is very slow.
913 eventTimestamp
= new LttngTimestamp(jniEvent
.getEventTime().getTime());
914 eventSource
= jniEvent
.requestEventSource();
915 eventReference
= getName();
916 eventType
= new LttngEventType(traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
)));
917 eventContent
= new LttngEventContent(currentLttngEvent
);
918 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
,
921 // The jni reference is no longer reliable but we will keep it anyhow
922 currentLttngEvent
.updateJniEventReference(jniEvent
);
923 // Ensure that the content is correctly set
924 eventContent
.setEvent(currentLttngEvent
);
926 // Parse the event if it was needed
928 // ONLY for testing, NOT parsing events with non-unique events WILL
929 // result in segfault in the JVM
931 eventContent
.getFields();
933 return currentLttngEvent
;
937 * Reference to the current LttngTrace we are reading from.
940 * Note : This bypass the framework and should not be use, except for
943 * @return Reference to the current LttngTrace
945 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
947 public JniTrace
getCurrentJniTrace() {
948 return currentJniTrace
;
952 * Return a reference to the current LttngEvent we have in memory.
954 * @return The current (last read) LttngEvent
956 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
958 public synchronized LttngEvent
getCurrentEvent() {
959 return currentLttngEvent
;
963 * Get the major version number for the current trace
965 * @return Version major or -1 if unknown
967 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
970 public short getVersionMajor() {
971 if (currentJniTrace
!= null)
972 return currentJniTrace
.getLttMajorVersion();
978 * Get the minor version number for the current trace
980 * @return Version minor or -1 if unknown
982 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
985 public short getVersionMinor() {
986 if (currentJniTrace
!= null)
987 return currentJniTrace
.getLttMinorVersion();
993 * Get the number of CPU for this trace
995 * @return Number of CPU or -1 if unknown
997 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
1000 public int getCpuNumber() {
1001 if (currentJniTrace
!= null)
1002 return currentJniTrace
.getCpuNumber();
1008 * Print the content of the checkpoint vector.
1011 * This is intended for debug purpose only.
1013 public void printCheckpointsVector() {
1014 System
.out
.println("StartTime : " //$NON-NLS-1$
1015 + getTimeRange().getStartTime().getValue());
1016 System
.out
.println("EndTime : " //$NON-NLS-1$
1017 + getTimeRange().getEndTime().getValue());
1019 for (int pos
= 0; pos
< fCheckpoints
.size(); pos
++) {
1020 System
.out
.print(pos
+ ": " + "\t"); //$NON-NLS-1$ //$NON-NLS-2$
1021 System
.out
.print(fCheckpoints
.get(pos
).getTimestamp() + "\t"); //$NON-NLS-1$
1022 System
.out
.println(fCheckpoints
.get(pos
).getLocation());
1027 public synchronized void dispose() {
1028 if (currentJniTrace
!= null)
1029 currentJniTrace
.closeTrace();
1034 * Return a String identifying this trace.
1036 * @return String that identify this trace
1039 @SuppressWarnings("nls")
1040 public String
toString() {
1041 String returnedData
= "";
1043 returnedData
+= "Path :" + getPath() + " ";
1044 returnedData
+= "Trace:" + currentJniTrace
+ " ";
1045 returnedData
+= "Event:" + currentLttngEvent
;
1047 return returnedData
;
1053 * EventTypeKey inner class
1055 * This class is used to make the process of generating the HashMap key more
1056 * transparent and so less error prone to use
1058 final class EventTypeKey
{
1061 // These two getEventTypeKey() functions should ALWAYS construct the key the
1063 // Otherwise, every type search will fail!
1065 // added final to encourage inlining.
1067 // generating a hash code by hand to avoid a string creation
1068 final static public int getEventTypeHash(final LttngEventType newEventType
) {
1069 return generateHash(newEventType
.getTracefileName(), newEventType
.getCpuId(), newEventType
.getMarkerName());
1072 final private static int generateHash(final String traceFileName
, final long cpuNumber
, final String markerName
) {
1073 // 0x1337 is a prime number. The number of CPUs is always under 8192 on
1074 // the current kernel, so this will work with the current linux kernel.
1075 final int cpuHash
= (int) (cpuNumber
* (0x1337));
1076 return traceFileName
.hashCode() ^
(cpuHash
) ^ markerName
.hashCode();
1079 // generating a hash code by hand to avoid a string creation
1080 final static public int getEventTypeHash(final JniEvent newEvent
) {
1081 return generateHash(newEvent
.getParentTracefile().getTracefileName(), newEvent
.getParentTracefile()
1082 .getCpuNumber(), newEvent
.requestEventMarker().getName());