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 // Position the trace at the checkpoint
541 final ITmfContext checkpointContext
= fIndexer
.seekIndex(rank
);
542 LttngLocation location
= (LttngLocation
) checkpointContext
.getLocation();
543 ITmfTimestamp timestamp
= location
.getLocation();
544 long index
= rank
/ getCacheSize();
546 // Seek to the found time
547 final TmfContext tmpContext
= seekEvent(timestamp
);
548 tmpContext
.setRank((index
+ 1) * fCacheSize
);
549 previousLocation
= (LttngLocation
) tmpContext
.getLocation();
551 // Ajust the index of the event we found at this check point position
552 Long currentPosition
= index
* getCacheSize();
554 Long lastTimeValueRead
= 0L;
556 // Get the event at current position. This won't move to the next one
557 JniEvent tmpJniEvent
= currentJniTrace
.findNextEvent();
558 // Now that we are positionned at the checkpoint,
559 // we need to "readNext" (Position - CheckpointPosition) times or until
561 while ((tmpJniEvent
!= null) && (currentPosition
< rank
)) {
562 tmpJniEvent
= currentJniTrace
.readNextEvent();
566 // If we found our event, save its timestamp
567 if (tmpJniEvent
!= null)
568 lastTimeValueRead
= tmpJniEvent
.getEventTime().getTime();
570 // Set the operation marker as seek, to be able to detect we did "seek"
572 previousLocation
.setLastOperationSeek();
573 // Save read event time
574 previousLocation
.setOperationTime(lastTimeValueRead
);
577 // Is that too paranoid?
579 // We don't trust what upper level could do with our internal location
580 // so we create a new one to return instead
581 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
583 return new TmfContext(curLocation
, rank
);
587 public TmfContext
seekLocation(final double ratio
) {
588 // TODO Auto-generated method stub
593 public double getLocationRatio(final ITmfLocation
<?
> location
) {
594 // TODO Auto-generated method stub
599 * Return the event in the trace according to the given context. Read it if
602 * Similar (same?) as ParseEvent except that calling GetNext twice read the
603 * next one the second time.
605 * @param context Current TmfContext where to get the event
607 * @return The LttngEvent we read of null if no event are available
609 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
610 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
613 public int nbEventsRead
= 0;
616 public synchronized LttngEvent
getNextEvent(final ITmfContext context
) {
619 System
.out
.println("getNextEvent(context) context.getLocation() -> " //$NON-NLS-1$
620 + context
.getLocation());
622 LttngEvent returnedEvent
= null;
623 LttngLocation curLocation
= null;
625 curLocation
= (LttngLocation
) context
.getLocation();
626 // If the location in context is null, create a new one
627 if (curLocation
== null)
628 curLocation
= getCurrentLocation(context
);
630 // *** Positioning trick :
631 // GetNextEvent only read the trace if :
632 // 1- The last operation was NOT a ParseEvent --> A read is required
634 // 2- The time of the previous location is different from the current
635 // one --> A seek + a read is required
636 if ((!(curLocation
.isLastOperationParse()))
637 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
638 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
640 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
641 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
642 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
643 seekEvent(curLocation
.getOperationTime());
645 // Read the next event from the trace. The last one will NO LONGER
647 returnedEvent
= readNextEvent(curLocation
);
650 // No event was read, just return the one currently loaded (the last
652 returnedEvent
= currentLttngEvent
;
654 // Set the operation marker as read to both locations, to be able to
655 // detect we need to read the next event
656 previousLocation
.setLastOperationReadNext();
657 curLocation
.setLastOperationReadNext();
660 // If we read an event, set it's time to the locations (both previous
662 if (returnedEvent
!= null)
663 setPreviousAndCurrentTimes(context
, returnedEvent
, curLocation
);
665 return returnedEvent
;
668 // this method was extracted for profiling purposes
669 private synchronized void setPreviousAndCurrentTimes(final ITmfContext context
, final LttngEvent returnedEvent
,
670 final LttngLocation curLocation
) {
672 final ITmfTimestamp eventTimestamp
= returnedEvent
.getTimestamp();
673 // long eventTime = eventTimestamp.getValue();
674 previousLocation
.setOperationTime(eventTimestamp
.getValue());
675 curLocation
.setOperationTime(eventTimestamp
.getValue());
676 updateAttributes(context
, eventTimestamp
);
677 context
.increaseRank();
680 // protected void updateIndex(TmfContext context, long rank, ITmfTimestamp timestamp) {
682 // if (getStartTime().compareTo(timestamp, false) > 0)
683 // setStartTime(timestamp);
684 // if (getEndTime().compareTo(timestamp, false) < 0)
685 // setEndTime(timestamp);
686 // if (rank != ITmfContext.UNKNOWN_RANK) {
687 // if (fNbEvents <= rank)
688 // fNbEvents = rank + 1;
689 // // Build the index as we go along
690 // if ((rank % fIndexPageSize) == 0) {
691 // // Determine the table position
692 // long position = rank / fIndexPageSize;
693 // // Add new entry at proper location (if empty)
694 // if (fCheckpoints.size() == position) {
695 // addCheckPoint(context, timestamp);
701 // this method was extracted for profiling purposes
702 private synchronized LttngEvent
readNextEvent(final LttngLocation curLocation
) {
703 LttngEvent returnedEvent
;
704 // Read the next event from the trace. The last one will NO LONGER BE
706 returnedEvent
= readEvent(curLocation
);
709 // Set the operation marker as read to both locations, to be able to
710 // detect we need to read the next event
711 previousLocation
.setLastOperationReadNext();
712 curLocation
.setLastOperationReadNext();
713 return returnedEvent
;
716 // this method was extracted for profiling purposes
717 private LttngLocation
getCurrentLocation(final ITmfContext context
) {
718 LttngLocation curLocation
;
719 curLocation
= new LttngLocation();
720 context
.setLocation(curLocation
);
725 * Return the event in the trace according to the given context. Read it if
728 * Similar (same?) as GetNextEvent except that calling ParseEvent twice will
729 * return the same event
731 * @param context Current TmfContext where to get the event
733 * @return The LttngEvent we read of null if no event are available
735 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
736 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
739 public synchronized LttngEvent
parseEvent(final ITmfContext context
) {
742 System
.out
.println("parseEvent(context) context.getLocation() -> " //$NON-NLS-1$
743 + context
.getLocation());
745 LttngEvent returnedEvent
= null;
746 LttngLocation curLocation
= null;
748 // If the location in context is null, create a new one
749 if (context
.getLocation() == null) {
750 curLocation
= new LttngLocation();
751 context
.setLocation(curLocation
);
753 curLocation
= (LttngLocation
) context
.getLocation();
756 // TMF assumes it is possible to read (GetNextEvent) to the next Event
757 // once ParseEvent() is called
758 // In LTTNG, there is not difference between "Parsing" and "Reading" an
760 // So, before "Parsing" an event, we have to make sure we didn't "Read"
762 // Also, "Reading" invalidate the previous Event in LTTNG and seek back
764 // so calling twice "Parse" will return the same event, giving a way to
765 // get the "Currently loaded" event
767 // *** Positionning trick :
768 // ParseEvent only read the trace if :
769 // 1- The last operation was NOT a ParseEvent --> A read is required
771 // 2- The time of the previous location is different from the current
772 // one --> A seek + a read is required
773 if (!curLocation
.isLastOperationParse()
774 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
775 // Previous time != Current time : We need to reposition to the
777 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
779 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
780 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
781 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
782 seekEvent(curLocation
.getOperationTime());
785 // Read the next event from the trace. The last one will NO LONGER
787 returnedEvent
= readEvent(curLocation
);
789 // No event was read, just return the one currently loaded (the last
791 returnedEvent
= currentLttngEvent
;
793 // If we read an event, set it's time to the locations (both previous
795 if (returnedEvent
!= null) {
796 previousLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
797 curLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
800 // Set the operation marker as parse to both location, to be able to
801 // detect we already "read" this event
802 previousLocation
.setLastOperationParse();
803 curLocation
.setLastOperationParse();
805 return returnedEvent
;
809 * Read the next event from the JNI and convert it as Lttng Event<p>
811 * @param location Current LttngLocation that to be updated with the event
814 * @return The LttngEvent we read of null if no event are available
816 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
818 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
820 private synchronized LttngEvent
readEvent(final LttngLocation location
) {
821 LttngEvent returnedEvent
= null;
822 JniEvent tmpEvent
= null;
824 // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG
826 tmpEvent
= currentJniTrace
.readNextEvent();
828 if (tmpEvent
!= null) {
830 // Convert will update the currentLttngEvent
831 returnedEvent
= convertJniEventToTmf(tmpEvent
);
833 location
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
835 location
.setOperationTime(getEndTime().getValue() + 1);
837 return returnedEvent
;
841 * Method to convert a JniEvent into a LttngEvent.
844 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent,
845 * boolean) with a default value for isParsingNeeded
847 * @param newEvent The JniEvent to convert into LttngEvent
849 * @return The converted LttngEvent
851 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
852 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
854 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent newEvent
) {
855 currentLttngEvent
= convertJniEventToTmf(newEvent
, IS_PARSING_NEEDED_DEFAULT
);
857 return currentLttngEvent
;
861 * Method to convert a JniEvent into a LttngEvent
863 * @param jniEvent The JniEvent to convert into LttngEvent
864 * @param isParsingNeeded A boolean value telling if the event should be
867 * @return The converted LttngEvent
869 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
870 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
872 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent jniEvent
, final boolean isParsingNeeded
) {
877 // UNHACKED : We can no longer do that because TCF need to maintain
878 // several events at once.
879 // This is very slow to do so in LTTng, this has to be temporary.
881 // To save time here, we only set value instead of allocating new
883 // This give an HUGE performance improvement
884 // all allocation done in the LttngTrace constructor
886 eventTimestamp
.setValue(jniEvent
.getEventTime().getTime());
887 eventSource
= jniEvent
.requestEventSource();
889 eventType
= traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
));
891 final String fullTracePath
= getName();
892 final String reference
= fullTracePath
.substring(fullTracePath
.lastIndexOf('/') + 1);
893 currentLttngEvent
.setReference(reference
);
895 eventContent
.emptyContent();
897 currentLttngEvent
.setType(eventType
);
898 // Save the jni reference
899 currentLttngEvent
.updateJniEventReference(jniEvent
);
901 // Parse now if was asked
902 // Warning : THIS IS SLOW
904 eventContent
.getFields();
906 return currentLttngEvent
;
908 return convertJniEventToTmfMultipleEventEvilFix(jniEvent
, isParsingNeeded
);
913 * This method is a temporary fix to support multiple events at once in TMF
914 * This is expected to be slow and should be fixed in another way. See
915 * comment in convertJniEventToTmf();
917 * @param jniEvent The current JNI Event
918 * @return Current Lttng Event fully parsed
920 private synchronized LttngEvent
convertJniEventToTmfMultipleEventEvilFix(final JniEvent jniEvent
,
921 final boolean isParsingNeeded
) {
923 // Below : the "fix" with all the new and the full-parse
924 // Allocating new memory is slow.
925 // Parsing every events is very slow.
926 eventTimestamp
= new LttngTimestamp(jniEvent
.getEventTime().getTime());
927 eventSource
= jniEvent
.requestEventSource();
928 eventReference
= getName();
929 eventType
= new LttngEventType(traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
)));
930 eventContent
= new LttngEventContent(currentLttngEvent
);
931 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
,
934 // The jni reference is no longer reliable but we will keep it anyhow
935 currentLttngEvent
.updateJniEventReference(jniEvent
);
936 // Ensure that the content is correctly set
937 eventContent
.setEvent(currentLttngEvent
);
939 // Parse the event if it was needed
941 // ONLY for testing, NOT parsing events with non-unique events WILL
942 // result in segfault in the JVM
944 eventContent
.getFields();
946 return currentLttngEvent
;
950 * Reference to the current LttngTrace we are reading from.
953 * Note : This bypass the framework and should not be use, except for
956 * @return Reference to the current LttngTrace
958 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
960 public JniTrace
getCurrentJniTrace() {
961 return currentJniTrace
;
965 * Return a reference to the current LttngEvent we have in memory.
967 * @return The current (last read) LttngEvent
969 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
971 public synchronized LttngEvent
getCurrentEvent() {
972 return currentLttngEvent
;
976 * Get the major version number for the current trace
978 * @return Version major or -1 if unknown
980 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
983 public short getVersionMajor() {
984 if (currentJniTrace
!= null)
985 return currentJniTrace
.getLttMajorVersion();
991 * Get the minor version number for the current trace
993 * @return Version minor or -1 if unknown
995 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
998 public short getVersionMinor() {
999 if (currentJniTrace
!= null)
1000 return currentJniTrace
.getLttMinorVersion();
1006 * Get the number of CPU for this trace
1008 * @return Number of CPU or -1 if unknown
1010 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
1013 public int getCpuNumber() {
1014 if (currentJniTrace
!= null)
1015 return currentJniTrace
.getCpuNumber();
1021 // * Print the content of the checkpoint vector.
1024 // * This is intended for debug purpose only.
1026 // public void printCheckpointsVector() {
1027 // System.out.println("StartTime : " //$NON-NLS-1$
1028 // + getTimeRange().getStartTime().getValue());
1029 // System.out.println("EndTime : " //$NON-NLS-1$
1030 // + getTimeRange().getEndTime().getValue());
1032 // for (int pos = 0; pos < fCheckpoints.size(); pos++) {
1033 // System.out.print(pos + ": " + "\t"); //$NON-NLS-1$ //$NON-NLS-2$
1034 // System.out.print(fCheckpoints.get(pos).getTimestamp() + "\t"); //$NON-NLS-1$
1035 // System.out.println(fCheckpoints.get(pos).getLocation());
1040 public synchronized void dispose() {
1041 if (currentJniTrace
!= null)
1042 currentJniTrace
.closeTrace();
1047 * Return a String identifying this trace.
1049 * @return String that identify this trace
1052 @SuppressWarnings("nls")
1053 public String
toString() {
1054 String returnedData
= "";
1056 returnedData
+= "Path :" + getPath() + " ";
1057 returnedData
+= "Trace:" + currentJniTrace
+ " ";
1058 returnedData
+= "Event:" + currentLttngEvent
;
1060 return returnedData
;
1066 * EventTypeKey inner class
1068 * This class is used to make the process of generating the HashMap key more
1069 * transparent and so less error prone to use
1071 final class EventTypeKey
{
1074 // These two getEventTypeKey() functions should ALWAYS construct the key the
1076 // Otherwise, every type search will fail!
1078 // added final to encourage inlining.
1080 // generating a hash code by hand to avoid a string creation
1081 final static public int getEventTypeHash(final LttngEventType newEventType
) {
1082 return generateHash(newEventType
.getTracefileName(), newEventType
.getCpuId(), newEventType
.getMarkerName());
1085 final private static int generateHash(final String traceFileName
, final long cpuNumber
, final String markerName
) {
1086 // 0x1337 is a prime number. The number of CPUs is always under 8192 on
1087 // the current kernel, so this will work with the current linux kernel.
1088 final int cpuHash
= (int) (cpuNumber
* (0x1337));
1089 return traceFileName
.hashCode() ^
(cpuHash
) ^ markerName
.hashCode();
1092 // generating a hash code by hand to avoid a string creation
1093 final static public int getEventTypeHash(final JniEvent newEvent
) {
1094 return generateHash(newEvent
.getParentTracefile().getTracefileName(), newEvent
.getParentTracefile()
1095 .getCpuNumber(), newEvent
.requestEventMarker().getName());