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
.core
.resources
.IResource
;
23 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.TraceHelper
;
24 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEvent
;
25 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventContent
;
26 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventType
;
27 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngLocation
;
28 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngTimestamp
;
29 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.exceptions
.LttngException
;
30 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.tracecontrol
.utility
.LiveTraceManager
;
31 import org
.eclipse
.linuxtools
.internal
.lttng
.jni
.common
.JniTime
;
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 IResource resource
, final String path
, final Class
<LttngEvent
> eventType
)
118 throws FileNotFoundException
{
119 super.initialize(resource
, path
, eventType
);
120 initialize(resource
, path
, eventType
);
124 protected synchronized void initialize(final IResource resource
, final String path
, final Class
<LttngEvent
> eventType
)
125 throws FileNotFoundException
{
127 currentJniTrace
= JniTraceFactory
.getJniTrace(path
, traceLibPath
, SHOW_LTT_DEBUG_DEFAULT
);
128 } catch (final Exception e
) {
129 throw new FileNotFoundException(e
.getMessage());
132 // Export all the event types from the JNI side
133 traceTypes
= new HashMap
<Integer
, LttngEventType
>();
134 traceTypeNames
= new Vector
<Integer
>();
135 initialiseEventTypes(currentJniTrace
);
137 // Build the re-used event structure
138 eventTimestamp
= new LttngTimestamp();
139 eventSource
= ""; //$NON-NLS-1$
140 this.eventType
= new LttngEventType();
141 eventContent
= new LttngEventContent(currentLttngEvent
);
142 eventReference
= getName();
144 // Create the skeleton event
145 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, this.eventType
, eventContent
,
146 eventReference
, null);
148 // Create a new current location
149 previousLocation
= new LttngLocation();
151 // Set the currentEvent to the eventContent
152 eventContent
.setEvent(currentLttngEvent
);
154 // // Bypass indexing if asked
155 // if ( bypassIndexing == false ) {
159 // Even if we don't have any index, set ONE checkpoint
160 // fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L) , new
161 // LttngLocation() ) );
163 initializeStreamingMonitor();
166 private void initializeStreamingMonitor() {
167 final JniTrace jniTrace
= getCurrentJniTrace();
169 || (!jniTrace
.isLiveTraceSupported() || !LiveTraceManager
.isLiveTrace(jniTrace
.getTracepath()))) {
170 // Set the time range of the trace
171 final TmfContext context
= seekLocation(null);
172 final LttngEvent event
= getNextEvent(context
);
173 final LttngTimestamp startTime
= new LttngTimestamp(event
.getTimestamp());
174 final LttngTimestamp endTime
= new LttngTimestamp(currentJniTrace
.getEndTime().getTime());
175 setTimeRange(new TmfTimeRange(startTime
, endTime
));
176 final TmfTraceUpdatedSignal signal
= new TmfTraceUpdatedSignal(this, this, getTimeRange());
181 // Set the time range of the trace
182 final TmfContext context
= seekLocation(null);
183 final LttngEvent event
= getNextEvent(context
);
184 setEndTime(TmfTimestamp
.BIG_BANG
);
185 final long startTime
= event
!= null ? event
.getTimestamp().getValue() : TmfTimestamp
.BIG_BANG
.getValue();
186 fStreamingInterval
= LTTNG_STREAMING_INTERVAL
;
188 final Thread thread
= new Thread("Streaming Monitor for trace " + getName()) { //$NON-NLS-1$
190 LttngTimestamp safeTimestamp
= null;
191 TmfTimeRange timeRange
= null;
193 @SuppressWarnings("unchecked")
196 while (!fExecutor
.isShutdown()) {
197 final TmfExperiment
<?
> experiment
= TmfExperiment
.getCurrentExperiment();
198 if (experiment
!= null) {
199 @SuppressWarnings("rawtypes")
200 final TmfEventRequest request
= new TmfEventRequest
<TmfEvent
>(TmfEvent
.class,
201 TmfTimeRange
.ETERNITY
, 0, ExecutionType
.FOREGROUND
) {
204 public void handleCompleted() {
208 synchronized (experiment
) {
209 experiment
.sendRequest(request
);
212 request
.waitForCompletion();
213 } catch (final InterruptedException e
) {
219 Thread
.sleep(LTTNG_STREAMING_INTERVAL
);
220 } catch (final InterruptedException e
) {
226 private void updateJniTrace() {
227 final JniTrace jniTrace
= getCurrentJniTrace();
228 currentJniTrace
.updateTrace();
229 final long endTime
= jniTrace
.getEndTime().getTime();
230 final LttngTimestamp startTimestamp
= new LttngTimestamp(startTime
);
231 final LttngTimestamp endTimestamp
= new LttngTimestamp(endTime
);
232 if (safeTimestamp
!= null && safeTimestamp
.compareTo(getTimeRange().getEndTime(), false) > 0)
233 timeRange
= new TmfTimeRange(startTimestamp
, safeTimestamp
);
236 safeTimestamp
= endTimestamp
;
237 if (timeRange
!= null)
238 setTimeRange(timeRange
);
245 * Default Constructor.
248 * @param name Name of the trace
249 * @param path Path to a <b>directory</b> that contain an LTTng trace.
251 * @exception Exception (most likely LTTngTraceException or
252 * FileNotFoundException)
254 public LTTngTrace(final IResource resource
, final String path
) throws Exception
{
255 // Call with "wait for completion" true and "skip indexing" false
256 this(resource
, path
, null, true, false);
260 * Constructor, with control over the indexing.
263 * @param name Name of the trace
264 * @param path Path to a <b>directory</b> that contain an LTTng trace.
265 * @param waitForCompletion Should we wait for indexign to complete before
268 * @exception Exception (most likely LTTngTraceException or
269 * FileNotFoundException)
271 public LTTngTrace(final IResource resource
, final String path
, final boolean waitForCompletion
) throws Exception
{
272 // Call with "skip indexing" false
273 this(resource
, path
, null, waitForCompletion
, true);
277 * Default constructor, with control over the indexing and possibility to
281 * @param name Name of the trace
282 * @param path Path to a <b>directory</b> that contain an LTTng trace.
283 * @param traceLibPath Path to a <b>directory</b> that contains LTTng trace
285 * @param waitForCompletion Should we wait for indexign to complete before
287 * @param bypassIndexing Should we bypass indexing completly? This is should
288 * only be useful for unit testing.
290 * @exception Exception (most likely LTTngTraceException or
291 * FileNotFoundException)
294 public LTTngTrace(final IResource resource
, final String path
, final String traceLibPath
, final boolean waitForCompletion
,
295 final boolean bypassIndexing
)
297 // super(resource, LttngEvent.class, path, CHECKPOINT_PAGE_SIZE, false);
298 super(resource
, LttngEvent
.class, path
, CHECKPOINT_PAGE_SIZE
);
299 initialize(resource
, path
, LttngEvent
.class);
300 // if (!bypassIndexing)
301 // indexTrace(false);
302 this.traceLibPath
= traceLibPath
;
306 * Copy constructor is forbidden for LttngEvenmStream
308 public LTTngTrace(final LTTngTrace other
) throws Exception
{
309 this(other
.getResource(), other
.getPath(), other
.getTraceLibPath(), false, true);
310 this.fCheckpoints
= other
.fCheckpoints
;
311 setTimeRange(new TmfTimeRange(new LttngTimestamp(other
.getStartTime()), new LttngTimestamp(other
.getEndTime())));
315 // public synchronized LTTngTrace clone() {
316 // LTTngTrace clone = null;
317 // clone = (LTTngTrace) super.clone();
319 // clone.currentJniTrace = JniTraceFactory.getJniTrace(getPath(), getTraceLibPath(),
320 // SHOW_LTT_DEBUG_DEFAULT);
321 // } catch (final JniException e) {
322 // // e.printStackTrace();
325 // // Export all the event types from the JNI side
326 // clone.traceTypes = new HashMap<Integer, LttngEventType>();
327 // clone.traceTypeNames = new Vector<Integer>();
328 // clone.initialiseEventTypes(clone.currentJniTrace);
330 // // Verify that all those "default constructor" are safe to use
331 // clone.eventTimestamp = new LttngTimestamp();
332 // clone.eventSource = ""; //$NON-NLS-1$
333 // clone.eventType = new LttngEventType();
334 // clone.eventContent = new LttngEventContent(clone.currentLttngEvent);
335 // clone.eventReference = getName();
337 // // Create the skeleton event
338 // clone.currentLttngEvent = new LttngEvent(this, clone.eventTimestamp, clone.eventSource, clone.eventType,
339 // clone.eventContent, clone.eventReference, null);
341 // // Create a new current location
342 // clone.previousLocation = new LttngLocation();
344 // // Set the currentEvent to the eventContent
345 // clone.eventContent.setEvent(clone.currentLttngEvent);
347 // // Set the start time of the trace
348 // setTimeRange(new TmfTimeRange(new LttngTimestamp(clone.currentJniTrace.getStartTime().getTime()),
349 // new LttngTimestamp(clone.currentJniTrace.getEndTime().getTime())));
354 public String
getTraceLibPath() {
359 * Fill out the HashMap with "Type" (Tracefile/Marker)
361 * This should be called at construction once the trace is open
363 private void initialiseEventTypes(final JniTrace trace
) {
365 LttngEventType tmpType
= null;
366 String
[] markerFieldsLabels
= null;
368 String newTracefileKey
= null;
369 Integer newMarkerKey
= null;
371 JniTracefile newTracefile
= null;
372 JniMarker newMarker
= null;
374 // First, obtain an iterator on TRACEFILES of owned by the TRACE
375 final Iterator
<String
> tracefileItr
= trace
.getTracefilesMap().keySet().iterator();
377 while (tracefileItr
.hasNext()) {
378 newTracefileKey
= tracefileItr
.next();
379 newTracefile
= trace
.getTracefilesMap().get(newTracefileKey
);
381 // From the TRACEFILE read, obtain its MARKER
382 final Iterator
<Integer
> markerItr
= newTracefile
.getTracefileMarkersMap().keySet().iterator();
383 while (markerItr
.hasNext()) {
384 newMarkerKey
= markerItr
.next();
385 newMarker
= newTracefile
.getTracefileMarkersMap().get(newMarkerKey
);
387 // From the MARKER we can obtain the MARKERFIELDS keys (i.e.
389 markerFieldsLabels
= newMarker
.getMarkerFieldsHashMap().keySet()
390 .toArray(new String
[newMarker
.getMarkerFieldsHashMap().size()]);
392 tmpType
= new LttngEventType(newTracefile
.getTracefileName(), newTracefile
.getCpuNumber(),
393 newMarker
.getName(), newMarkerKey
.intValue(), markerFieldsLabels
);
395 // Add the type to the map/vector
396 addEventTypeToMap(tmpType
);
402 * Add a new type to the HashMap
404 * As the hashmap use a key format that is a bit dangerous to use, we should
405 * always add using this function.
407 private void addEventTypeToMap(final LttngEventType newEventType
) {
408 final int newTypeKey
= EventTypeKey
.getEventTypeHash(newEventType
);
410 this.traceTypes
.put(newTypeKey
, newEventType
);
411 this.traceTypeNames
.add(newTypeKey
);
415 * Return the latest saved location. Note : Modifying the returned location
416 * may result in buggy positionning!
418 * @return The LttngLocation as it was after the last operation.
420 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
423 public synchronized ITmfLocation
<?
> getCurrentLocation() {
424 return previousLocation
;
428 * Position the trace to the event at the given location.
430 * NOTE : Seeking by location is very fast compare to seeking by position
431 * but is still slower than "ReadNext", avoid using it for small interval.
433 * @param location Location of the event in the trace. If no event available
434 * at this exact location, we will position ourself to the next
437 * @return The TmfContext that point to this event
439 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
440 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
443 public synchronized TmfContext
seekLocation(final ITmfLocation
<?
> location
) {
449 System
.out
.println("seekLocation(location) location -> " + location
); //$NON-NLS-1$
451 // If the location in context is null, create a new one
452 LttngLocation curLocation
= null;
453 if (location
== null) {
454 curLocation
= new LttngLocation();
455 final TmfContext context
= seekEvent(curLocation
.getOperationTime());
456 context
.setRank(ITmfContext
.INITIAL_RANK
);
459 curLocation
= (LttngLocation
) location
;
462 // Update to location should (and will) be done in SeekEvent.
464 // The only seek valid in LTTng is with the time, we call
465 // seekEvent(timestamp)
466 final TmfContext context
= seekEvent(curLocation
.getOperationTime());
468 // If the location is marked with the read next flag
469 // then it is pointing to the next event following the operation time
470 if (curLocation
.isLastOperationReadNext())
471 getNextEvent(context
);
477 * Position the trace to the event at the given time.
479 * NOTE : Seeking by time is very fast compare to seeking by position but is
480 * still slower than "ReadNext", avoid using it for small interval.
482 * @param timestamp Time of the event in the trace. If no event available at
483 * this exact time, we will position ourself to the next one.
485 * @return The TmfContext that point to this event
487 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
488 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
491 public synchronized TmfContext
seekEvent(final ITmfTimestamp timestamp
) {
494 System
.out
.println("seekEvent(timestamp) timestamp -> " + timestamp
); //$NON-NLS-1$
497 currentJniTrace
.seekToTime(new JniTime(timestamp
.getValue()));
499 // Save the time at which we seeked
500 previousLocation
.setOperationTime(timestamp
.getValue());
501 // Set the operation marker as seek, to be able to detect we did "seek"
503 previousLocation
.setLastOperationSeek();
505 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
507 return new TmfContext(curLocation
);
511 * Position the trace to the event at the given position (rank).
513 * NOTE : Seeking by position is very slow in LTTng, consider seeking by
516 * @param rank Position (or rank) of the event in the trace, starting at 0.
518 * @return The TmfContext that point to this event
520 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
521 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
524 public synchronized TmfContext
seekEvent(final long rank
) {
527 System
.out
.println("seekEvent(rank) rank -> " + rank
); //$NON-NLS-1$
529 ITmfTimestamp timestamp
= null;
530 long index
= rank
/ getCacheSize();
532 // Get the timestamp of the closest check point to the given position
533 if (fCheckpoints
.size() > 0) {
534 if (index
>= fCheckpoints
.size())
535 index
= fCheckpoints
.size() - 1;
536 timestamp
= fCheckpoints
.elementAt((int) index
).getTimestamp();
538 timestamp
= getStartTime();
540 // Seek to the found time
541 final TmfContext tmpContext
= seekEvent(timestamp
);
542 tmpContext
.setRank((index
+ 1) * fCacheSize
);
543 previousLocation
= (LttngLocation
) tmpContext
.getLocation();
545 // Ajust the index of the event we found at this check point position
546 Long currentPosition
= index
* getCacheSize();
548 Long lastTimeValueRead
= 0L;
550 // Get the event at current position. This won't move to the next one
551 JniEvent tmpJniEvent
= currentJniTrace
.findNextEvent();
552 // Now that we are positionned at the checkpoint,
553 // we need to "readNext" (Position - CheckpointPosition) times or until
555 while ((tmpJniEvent
!= null) && (currentPosition
< rank
)) {
556 tmpJniEvent
= currentJniTrace
.readNextEvent();
560 // If we found our event, save its timestamp
561 if (tmpJniEvent
!= null)
562 lastTimeValueRead
= tmpJniEvent
.getEventTime().getTime();
564 // Set the operation marker as seek, to be able to detect we did "seek"
566 previousLocation
.setLastOperationSeek();
567 // Save read event time
568 previousLocation
.setOperationTime(lastTimeValueRead
);
571 // Is that too paranoid?
573 // We don't trust what upper level could do with our internal location
574 // so we create a new one to return instead
575 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
577 return new TmfContext(curLocation
, rank
);
581 public TmfContext
seekLocation(final double ratio
) {
582 // TODO Auto-generated method stub
587 public double getLocationRatio(final ITmfLocation
<?
> location
) {
588 // TODO Auto-generated method stub
593 * Return the event in the trace according to the given context. Read it if
596 * Similar (same?) as ParseEvent except that calling GetNext twice read the
597 * next one the second time.
599 * @param context Current TmfContext where to get the event
601 * @return The LttngEvent we read of null if no event are available
603 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
604 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
607 public int nbEventsRead
= 0;
610 public synchronized LttngEvent
getNextEvent(final ITmfContext context
) {
613 System
.out
.println("getNextEvent(context) context.getLocation() -> " //$NON-NLS-1$
614 + context
.getLocation());
616 LttngEvent returnedEvent
= null;
617 LttngLocation curLocation
= null;
619 curLocation
= (LttngLocation
) context
.getLocation();
620 // If the location in context is null, create a new one
621 if (curLocation
== null)
622 curLocation
= getCurrentLocation(context
);
624 // *** Positioning trick :
625 // GetNextEvent only read the trace if :
626 // 1- The last operation was NOT a ParseEvent --> A read is required
628 // 2- The time of the previous location is different from the current
629 // one --> A seek + a read is required
630 if ((!(curLocation
.isLastOperationParse()))
631 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
632 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
634 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
635 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
636 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
637 seekEvent(curLocation
.getOperationTime());
639 // Read the next event from the trace. The last one will NO LONGER
641 returnedEvent
= readNextEvent(curLocation
);
644 // No event was read, just return the one currently loaded (the last
646 returnedEvent
= currentLttngEvent
;
648 // Set the operation marker as read to both locations, to be able to
649 // detect we need to read the next event
650 previousLocation
.setLastOperationReadNext();
651 curLocation
.setLastOperationReadNext();
654 // If we read an event, set it's time to the locations (both previous
656 if (returnedEvent
!= null)
657 setPreviousAndCurrentTimes(context
, returnedEvent
, curLocation
);
659 return returnedEvent
;
662 // this method was extracted for profiling purposes
663 private synchronized void setPreviousAndCurrentTimes(final ITmfContext context
, final LttngEvent returnedEvent
,
664 final LttngLocation curLocation
) {
666 final ITmfTimestamp eventTimestamp
= returnedEvent
.getTimestamp();
667 // long eventTime = eventTimestamp.getValue();
668 previousLocation
.setOperationTime(eventTimestamp
.getValue());
669 curLocation
.setOperationTime(eventTimestamp
.getValue());
670 updateIndex(context
, context
.getRank(), eventTimestamp
);
671 context
.increaseRank();
674 // protected void updateIndex(TmfContext context, long rank, ITmfTimestamp timestamp) {
676 // if (getStartTime().compareTo(timestamp, false) > 0)
677 // setStartTime(timestamp);
678 // if (getEndTime().compareTo(timestamp, false) < 0)
679 // setEndTime(timestamp);
680 // if (rank != ITmfContext.UNKNOWN_RANK) {
681 // if (fNbEvents <= rank)
682 // fNbEvents = rank + 1;
683 // // Build the index as we go along
684 // if ((rank % fIndexPageSize) == 0) {
685 // // Determine the table position
686 // long position = rank / fIndexPageSize;
687 // // Add new entry at proper location (if empty)
688 // if (fCheckpoints.size() == position) {
689 // addCheckPoint(context, timestamp);
695 // this method was extracted for profiling purposes
696 private synchronized LttngEvent
readNextEvent(final LttngLocation curLocation
) {
697 LttngEvent returnedEvent
;
698 // Read the next event from the trace. The last one will NO LONGER BE
700 returnedEvent
= readEvent(curLocation
);
703 // Set the operation marker as read to both locations, to be able to
704 // detect we need to read the next event
705 previousLocation
.setLastOperationReadNext();
706 curLocation
.setLastOperationReadNext();
707 return returnedEvent
;
710 // this method was extracted for profiling purposes
711 private LttngLocation
getCurrentLocation(final ITmfContext context
) {
712 LttngLocation curLocation
;
713 curLocation
= new LttngLocation();
714 context
.setLocation(curLocation
);
719 * Return the event in the trace according to the given context. Read it if
722 * Similar (same?) as GetNextEvent except that calling ParseEvent twice will
723 * return the same event
725 * @param context Current TmfContext where to get the event
727 * @return The LttngEvent we read of null if no event are available
729 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
730 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
733 public synchronized LttngEvent
parseEvent(final ITmfContext context
) {
736 System
.out
.println("parseEvent(context) context.getLocation() -> " //$NON-NLS-1$
737 + context
.getLocation());
739 LttngEvent returnedEvent
= null;
740 LttngLocation curLocation
= null;
742 // If the location in context is null, create a new one
743 if (context
.getLocation() == null) {
744 curLocation
= new LttngLocation();
745 context
.setLocation(curLocation
);
747 curLocation
= (LttngLocation
) context
.getLocation();
750 // TMF assumes it is possible to read (GetNextEvent) to the next Event
751 // once ParseEvent() is called
752 // In LTTNG, there is not difference between "Parsing" and "Reading" an
754 // So, before "Parsing" an event, we have to make sure we didn't "Read"
756 // Also, "Reading" invalidate the previous Event in LTTNG and seek back
758 // so calling twice "Parse" will return the same event, giving a way to
759 // get the "Currently loaded" event
761 // *** Positionning trick :
762 // ParseEvent only read the trace if :
763 // 1- The last operation was NOT a ParseEvent --> A read is required
765 // 2- The time of the previous location is different from the current
766 // one --> A seek + a read is required
767 if (!curLocation
.isLastOperationParse()
768 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
769 // Previous time != Current time : We need to reposition to the
771 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
773 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
774 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
775 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
776 seekEvent(curLocation
.getOperationTime());
779 // Read the next event from the trace. The last one will NO LONGER
781 returnedEvent
= readEvent(curLocation
);
783 // No event was read, just return the one currently loaded (the last
785 returnedEvent
= currentLttngEvent
;
787 // If we read an event, set it's time to the locations (both previous
789 if (returnedEvent
!= null) {
790 previousLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
791 curLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
794 // Set the operation marker as parse to both location, to be able to
795 // detect we already "read" this event
796 previousLocation
.setLastOperationParse();
797 curLocation
.setLastOperationParse();
799 return returnedEvent
;
803 * Read the next event from the JNI and convert it as Lttng Event<p>
805 * @param location Current LttngLocation that to be updated with the event
808 * @return The LttngEvent we read of null if no event are available
810 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
812 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
814 private synchronized LttngEvent
readEvent(final LttngLocation location
) {
815 LttngEvent returnedEvent
= null;
816 JniEvent tmpEvent
= null;
818 // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG
820 tmpEvent
= currentJniTrace
.readNextEvent();
822 if (tmpEvent
!= null) {
824 // Convert will update the currentLttngEvent
825 returnedEvent
= convertJniEventToTmf(tmpEvent
);
827 location
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
829 location
.setOperationTime(getEndTime().getValue() + 1);
831 return returnedEvent
;
835 * Method to convert a JniEvent into a LttngEvent.
838 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent,
839 * boolean) with a default value for isParsingNeeded
841 * @param newEvent The JniEvent to convert into LttngEvent
843 * @return The converted LttngEvent
845 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
846 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
848 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent newEvent
) {
849 currentLttngEvent
= convertJniEventToTmf(newEvent
, IS_PARSING_NEEDED_DEFAULT
);
851 return currentLttngEvent
;
855 * Method to convert a JniEvent into a LttngEvent
857 * @param jniEvent The JniEvent to convert into LttngEvent
858 * @param isParsingNeeded A boolean value telling if the event should be
861 * @return The converted LttngEvent
863 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
864 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
866 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent jniEvent
, final boolean isParsingNeeded
) {
871 // UNHACKED : We can no longer do that because TCF need to maintain
872 // several events at once.
873 // This is very slow to do so in LTTng, this has to be temporary.
875 // To save time here, we only set value instead of allocating new
877 // This give an HUGE performance improvement
878 // all allocation done in the LttngTrace constructor
880 eventTimestamp
.setValue(jniEvent
.getEventTime().getTime());
881 eventSource
= jniEvent
.requestEventSource();
883 eventType
= traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
));
885 final String fullTracePath
= getName();
886 final String reference
= fullTracePath
.substring(fullTracePath
.lastIndexOf('/') + 1);
887 currentLttngEvent
.setReference(reference
);
889 eventContent
.emptyContent();
891 currentLttngEvent
.setType(eventType
);
892 // Save the jni reference
893 currentLttngEvent
.updateJniEventReference(jniEvent
);
895 // Parse now if was asked
896 // Warning : THIS IS SLOW
898 eventContent
.getFields();
900 return currentLttngEvent
;
902 return convertJniEventToTmfMultipleEventEvilFix(jniEvent
, isParsingNeeded
);
907 * This method is a temporary fix to support multiple events at once in TMF
908 * This is expected to be slow and should be fixed in another way. See
909 * comment in convertJniEventToTmf();
911 * @param jniEvent The current JNI Event
912 * @return Current Lttng Event fully parsed
914 private synchronized LttngEvent
convertJniEventToTmfMultipleEventEvilFix(final JniEvent jniEvent
,
915 final boolean isParsingNeeded
) {
917 // Below : the "fix" with all the new and the full-parse
918 // Allocating new memory is slow.
919 // Parsing every events is very slow.
920 eventTimestamp
= new LttngTimestamp(jniEvent
.getEventTime().getTime());
921 eventSource
= jniEvent
.requestEventSource();
922 eventReference
= getName();
923 eventType
= new LttngEventType(traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
)));
924 eventContent
= new LttngEventContent(currentLttngEvent
);
925 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
,
928 // The jni reference is no longer reliable but we will keep it anyhow
929 currentLttngEvent
.updateJniEventReference(jniEvent
);
930 // Ensure that the content is correctly set
931 eventContent
.setEvent(currentLttngEvent
);
933 // Parse the event if it was needed
935 // ONLY for testing, NOT parsing events with non-unique events WILL
936 // result in segfault in the JVM
938 eventContent
.getFields();
940 return currentLttngEvent
;
944 * Reference to the current LttngTrace we are reading from.
947 * Note : This bypass the framework and should not be use, except for
950 * @return Reference to the current LttngTrace
952 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
954 public JniTrace
getCurrentJniTrace() {
955 return currentJniTrace
;
959 * Return a reference to the current LttngEvent we have in memory.
961 * @return The current (last read) LttngEvent
963 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
965 public synchronized LttngEvent
getCurrentEvent() {
966 return currentLttngEvent
;
970 * Get the major version number for the current trace
972 * @return Version major or -1 if unknown
974 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
977 public short getVersionMajor() {
978 if (currentJniTrace
!= null)
979 return currentJniTrace
.getLttMajorVersion();
985 * Get the minor version number for the current trace
987 * @return Version minor or -1 if unknown
989 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
992 public short getVersionMinor() {
993 if (currentJniTrace
!= null)
994 return currentJniTrace
.getLttMinorVersion();
1000 * Get the number of CPU for this trace
1002 * @return Number of CPU or -1 if unknown
1004 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
1007 public int getCpuNumber() {
1008 if (currentJniTrace
!= null)
1009 return currentJniTrace
.getCpuNumber();
1015 * Print the content of the checkpoint vector.
1018 * This is intended for debug purpose only.
1020 public void printCheckpointsVector() {
1021 System
.out
.println("StartTime : " //$NON-NLS-1$
1022 + getTimeRange().getStartTime().getValue());
1023 System
.out
.println("EndTime : " //$NON-NLS-1$
1024 + getTimeRange().getEndTime().getValue());
1026 for (int pos
= 0; pos
< fCheckpoints
.size(); pos
++) {
1027 System
.out
.print(pos
+ ": " + "\t"); //$NON-NLS-1$ //$NON-NLS-2$
1028 System
.out
.print(fCheckpoints
.get(pos
).getTimestamp() + "\t"); //$NON-NLS-1$
1029 System
.out
.println(fCheckpoints
.get(pos
).getLocation());
1034 public synchronized void dispose() {
1035 if (currentJniTrace
!= null)
1036 currentJniTrace
.closeTrace();
1041 * Return a String identifying this trace.
1043 * @return String that identify this trace
1046 @SuppressWarnings("nls")
1047 public String
toString() {
1048 String returnedData
= "";
1050 returnedData
+= "Path :" + getPath() + " ";
1051 returnedData
+= "Trace:" + currentJniTrace
+ " ";
1052 returnedData
+= "Event:" + currentLttngEvent
;
1054 return returnedData
;
1060 * EventTypeKey inner class
1062 * This class is used to make the process of generating the HashMap key more
1063 * transparent and so less error prone to use
1065 final class EventTypeKey
{
1068 // These two getEventTypeKey() functions should ALWAYS construct the key the
1070 // Otherwise, every type search will fail!
1072 // added final to encourage inlining.
1074 // generating a hash code by hand to avoid a string creation
1075 final static public int getEventTypeHash(final LttngEventType newEventType
) {
1076 return generateHash(newEventType
.getTracefileName(), newEventType
.getCpuId(), newEventType
.getMarkerName());
1079 final private static int generateHash(final String traceFileName
, final long cpuNumber
, final String markerName
) {
1080 // 0x1337 is a prime number. The number of CPUs is always under 8192 on
1081 // the current kernel, so this will work with the current linux kernel.
1082 final int cpuHash
= (int) (cpuNumber
* (0x1337));
1083 return traceFileName
.hashCode() ^
(cpuHash
) ^ markerName
.hashCode();
1086 // generating a hash code by hand to avoid a string creation
1087 final static public int getEventTypeHash(final JniEvent newEvent
) {
1088 return generateHash(newEvent
.getParentTracefile().getTracefileName(), newEvent
.getParentTracefile()
1089 .getCpuNumber(), newEvent
.requestEventMarker().getName());