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
.util
.HashMap
;
17 import java
.util
.Iterator
;
18 import java
.util
.Vector
;
20 import org
.eclipse
.core
.resources
.IProject
;
21 import org
.eclipse
.core
.resources
.IResource
;
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
.lttng
.jni
.JniEvent
;
32 import org
.eclipse
.linuxtools
.lttng
.jni
.JniMarker
;
33 import org
.eclipse
.linuxtools
.lttng
.jni
.JniTrace
;
34 import org
.eclipse
.linuxtools
.lttng
.jni
.JniTracefile
;
35 import org
.eclipse
.linuxtools
.lttng
.jni
.factory
.JniTraceFactory
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfEvent
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TmfTraceException
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
.ExecutionType
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfEventRequest
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceUpdatedSignal
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfEventParser
;
46 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
47 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfCheckpointIndexer
;
48 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
49 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
50 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
52 class LTTngTraceException
extends LttngException
{
54 static final long serialVersionUID
= -1636648737081868146L;
56 public LTTngTraceException(final String errMsg
) {
62 * <b><u>LTTngTrace</u></b>
65 * LTTng trace implementation. It accesses the C trace handling library
66 * (seeking, reading and parsing) through the JNI component.
68 public class LTTngTrace
extends TmfTrace
<LttngEvent
> implements ITmfEventParser
<LttngEvent
> {
70 public final static boolean PRINT_DEBUG
= false;
71 public final static boolean UNIQUE_EVENT
= true;
73 private final static boolean SHOW_LTT_DEBUG_DEFAULT
= false;
74 private final static boolean IS_PARSING_NEEDED_DEFAULT
= !UNIQUE_EVENT
;
75 private final static int CHECKPOINT_PAGE_SIZE
= 50000;
76 private final static long LTTNG_STREAMING_INTERVAL
= 2000; // in ms
78 // Reference to our JNI trace
79 private JniTrace currentJniTrace
;
81 LttngTimestamp eventTimestamp
;
83 LttngEventContent eventContent
;
84 String eventReference
;
87 LttngEvent currentLttngEvent
;
89 // The current location
90 LttngLocation previousLocation
;
92 LttngEventType eventType
;
94 // Hashmap of the possible types of events (Tracefile/CPU/Marker in the JNI)
95 HashMap
<Integer
, LttngEventType
> traceTypes
;
97 // This vector will be used to quickly find a marker name from a position
98 Vector
<Integer
> traceTypeNames
;
100 private String traceLibPath
;
102 public LTTngTrace() {
106 public boolean validate(final IProject project
, final String path
) {
107 if (fileExists(path
)) {
108 final String traceLibPath
= TraceHelper
.getTraceLibDirFromProject(project
);
110 final LTTngTraceVersion version
= new LTTngTraceVersion(path
, traceLibPath
);
111 return version
.isValidLttngTrace();
112 } catch (final LttngException e
) {
118 @SuppressWarnings({ "unchecked", "rawtypes" })
120 public synchronized void initTrace(final IResource resource
, final String path
, final Class
<LttngEvent
> eventType
)
121 throws TmfTraceException
{
122 super.initialize(resource
, path
, eventType
);
123 setIndexer(new TmfCheckpointIndexer(this, getCacheSize()));
124 initialize(resource
, path
, eventType
);
128 protected synchronized void initialize(final IResource resource
, final String path
, final Class
<LttngEvent
> eventType
)
129 throws TmfTraceException
{
131 if (resource
!= null) {
132 IProject project
= resource
.getProject();
133 traceLibPath
= (project
!= null) ? TraceHelper
.getTraceLibDirFromProject(project
) : null;
135 currentJniTrace
= JniTraceFactory
.getJniTrace(path
, traceLibPath
, SHOW_LTT_DEBUG_DEFAULT
);
136 } catch (final Exception e
) {
137 throw new TmfTraceException(e
.getMessage());
140 // Export all the event types from the JNI side
141 traceTypes
= new HashMap
<Integer
, LttngEventType
>();
142 traceTypeNames
= new Vector
<Integer
>();
143 initialiseEventTypes(currentJniTrace
);
145 // Build the re-used event structure
146 eventTimestamp
= new LttngTimestamp();
147 eventSource
= ""; //$NON-NLS-1$
148 this.eventType
= new LttngEventType();
149 eventContent
= new LttngEventContent(currentLttngEvent
);
150 eventReference
= getName();
152 // Create the skeleton event
153 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, this.eventType
, eventContent
,
154 eventReference
, null);
156 // Create a new current location
157 previousLocation
= new LttngLocation();
159 // Set the currentEvent to the eventContent
160 eventContent
.setEvent(currentLttngEvent
);
162 setParser((ITmfEventParser
<LttngEvent
>) this);
163 setCacheSize(CHECKPOINT_PAGE_SIZE
);
165 initializeStreamingMonitor();
168 private void initializeStreamingMonitor() {
169 final JniTrace jniTrace
= getCurrentJniTrace();
171 || (!jniTrace
.isLiveTraceSupported() || !LiveTraceManager
.isLiveTrace(jniTrace
.getTracepath()))) {
172 // Set the time range of the trace
173 final ITmfContext context
= seekEvent(0);
174 final LttngEvent event
= getNext(context
);
175 final LttngTimestamp startTime
= new LttngTimestamp(event
.getTimestamp());
176 final LttngTimestamp endTime
= new LttngTimestamp(currentJniTrace
.getEndTime().getTime());
177 setTimeRange(new TmfTimeRange(startTime
, endTime
));
178 final TmfTraceUpdatedSignal signal
= new TmfTraceUpdatedSignal(this, this, getTimeRange());
183 // Set the time range of the trace
184 final ITmfContext context
= seekEvent(0);
185 final LttngEvent event
= getNext(context
);
186 setEndTime(TmfTimestamp
.BIG_BANG
);
187 final long startTime
= event
!= null ? event
.getTimestamp().getValue() : TmfTimestamp
.BIG_BANG
.getValue();
188 setStreamingInterval(LTTNG_STREAMING_INTERVAL
);
190 final Thread thread
= new Thread("Streaming Monitor for trace " + getName()) { //$NON-NLS-1$
192 LttngTimestamp safeTimestamp
= null;
193 TmfTimeRange timeRange
= null;
195 @SuppressWarnings({ "unchecked", "restriction" })
198 while (!fExecutor
.isShutdown()) {
199 final TmfExperiment
<?
> experiment
= TmfExperiment
.getCurrentExperiment();
200 if (experiment
!= null) {
201 @SuppressWarnings("rawtypes")
202 final TmfEventRequest request
= new TmfEventRequest
<TmfEvent
>(TmfEvent
.class,
203 TmfTimeRange
.ETERNITY
, 0, ExecutionType
.FOREGROUND
) {
206 public void handleCompleted() {
210 synchronized (experiment
) {
211 experiment
.sendRequest(request
);
214 request
.waitForCompletion();
215 } catch (final InterruptedException e
) {
220 Thread
.sleep(LTTNG_STREAMING_INTERVAL
);
221 } 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 setTimeRange(new TmfTimeRange(new LttngTimestamp(other
.getStartTime()), new LttngTimestamp(other
.getEndTime())));
313 public String
getTraceLibPath() {
318 * Fill out the HashMap with "Type" (Tracefile/Marker)
320 * This should be called at construction once the trace is open
322 private void initialiseEventTypes(final JniTrace trace
) {
324 LttngEventType tmpType
= null;
325 String
[] markerFieldsLabels
= null;
327 String newTracefileKey
= null;
328 Integer newMarkerKey
= null;
330 JniTracefile newTracefile
= null;
331 JniMarker newMarker
= null;
333 // First, obtain an iterator on TRACEFILES of owned by the TRACE
334 final Iterator
<String
> tracefileItr
= trace
.getTracefilesMap().keySet().iterator();
336 while (tracefileItr
.hasNext()) {
337 newTracefileKey
= tracefileItr
.next();
338 newTracefile
= trace
.getTracefilesMap().get(newTracefileKey
);
340 // From the TRACEFILE read, obtain its MARKER
341 final Iterator
<Integer
> markerItr
= newTracefile
.getTracefileMarkersMap().keySet().iterator();
342 while (markerItr
.hasNext()) {
343 newMarkerKey
= markerItr
.next();
344 newMarker
= newTracefile
.getTracefileMarkersMap().get(newMarkerKey
);
346 // From the MARKER we can obtain the MARKERFIELDS keys (i.e.
348 markerFieldsLabels
= newMarker
.getMarkerFieldsHashMap().keySet()
349 .toArray(new String
[newMarker
.getMarkerFieldsHashMap().size()]);
351 tmpType
= new LttngEventType(newTracefile
.getTracefileName(), newTracefile
.getCpuNumber(),
352 newMarker
.getName(), newMarkerKey
.intValue(), markerFieldsLabels
);
354 // Add the type to the map/vector
355 addEventTypeToMap(tmpType
);
361 * Add a new type to the HashMap
363 * As the hashmap use a key format that is a bit dangerous to use, we should
364 * always add using this function.
366 private void addEventTypeToMap(final LttngEventType newEventType
) {
367 final int newTypeKey
= EventTypeKey
.getEventTypeHash(newEventType
);
369 this.traceTypes
.put(newTypeKey
, newEventType
);
370 this.traceTypeNames
.add(newTypeKey
);
374 * Return the latest saved location. Note : Modifying the returned location
375 * may result in buggy positionning!
377 * @return The LttngLocation as it was after the last operation.
379 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
382 public synchronized ITmfLocation
<?
> getCurrentLocation() {
383 return previousLocation
;
387 * Position the trace to the event at the given location.
389 * NOTE : Seeking by location is very fast compare to seeking by position
390 * but is still slower than "ReadNext", avoid using it for small interval.
392 * @param location Location of the event in the trace. If no event available
393 * at this exact location, we will position ourself to the next
396 * @return The TmfContext that point to this event
398 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
399 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
402 public synchronized ITmfContext
seekEvent(final ITmfLocation
<?
> location
) {
405 System
.out
.println("seekLocation(location) location -> " + location
); //$NON-NLS-1$
407 // If the location in context is null, create a new one
408 if (location
== null) {
409 LttngLocation curLocation
= new LttngLocation();
410 final ITmfContext context
= seekEvent(curLocation
.getOperationTime());
415 // The only seek valid in LTTng is with the time, we call
416 // seekEvent(timestamp)
417 LttngLocation curLocation
= (LttngLocation
) location
;
418 final ITmfContext context
= seekEvent(curLocation
.getOperationTime());
420 // If the location is marked with the read next flag
421 // then it is pointing to the next event following the operation time
422 if (curLocation
.isLastOperationReadNext())
429 * Position the trace to the event at the given time.
431 * NOTE : Seeking by time is very fast compare to seeking by position but is
432 * still slower than "ReadNext", avoid using it for small interval.
434 * @param timestamp Time of the event in the trace. If no event available at
435 * this exact time, we will position ourself to the next one.
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
seekEvent(final ITmfTimestamp timestamp
) {
446 System
.out
.println("seekEvent(timestamp) timestamp -> " + timestamp
); //$NON-NLS-1$
449 currentJniTrace
.seekToTime(new JniTime(timestamp
.getValue()));
451 // Save the time at which we seeked
452 previousLocation
.setOperationTime(timestamp
.getValue());
453 // Set the operation marker as seek, to be able to detect we did "seek"
455 previousLocation
.setLastOperationSeek();
457 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
459 return new TmfContext(curLocation
);
463 * Position the trace to the event at the given position (rank).
465 * NOTE : Seeking by position is very slow in LTTng, consider seeking by
468 * @param rank Position (or rank) of the event in the trace, starting at 0.
470 * @return The TmfContext that point to this event
472 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
473 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
476 public synchronized TmfContext
seekEvent(final long rank
) {
479 System
.out
.println("seekEvent(rank) rank -> " + rank
); //$NON-NLS-1$
481 // Position the trace at the checkpoint
482 final ITmfContext checkpointContext
= getIndexer().seekIndex(rank
);
483 LttngLocation location
= (LttngLocation
) checkpointContext
.getLocation();
484 ITmfTimestamp timestamp
= location
.getLocation();
485 long index
= rank
/ getCacheSize();
487 // Seek to the found time
488 final TmfContext tmpContext
= seekEvent(timestamp
);
489 tmpContext
.setRank((index
+ 1) * getCacheSize());
490 previousLocation
= (LttngLocation
) tmpContext
.getLocation();
492 // Ajust the index of the event we found at this check point position
493 Long currentPosition
= index
* getCacheSize();
495 Long lastTimeValueRead
= 0L;
497 // Get the event at current position. This won't move to the next one
498 JniEvent tmpJniEvent
= currentJniTrace
.findNextEvent();
499 // Now that we are positionned at the checkpoint,
500 // we need to "readNext" (Position - CheckpointPosition) times or until
502 while ((tmpJniEvent
!= null) && (currentPosition
< rank
)) {
503 tmpJniEvent
= currentJniTrace
.readNextEvent();
507 // If we found our event, save its timestamp
508 if (tmpJniEvent
!= null)
509 lastTimeValueRead
= tmpJniEvent
.getEventTime().getTime();
511 // Set the operation marker as seek, to be able to detect we did "seek"
513 previousLocation
.setLastOperationSeek();
514 // Save read event time
515 previousLocation
.setOperationTime(lastTimeValueRead
);
518 // Is that too paranoid?
520 // We don't trust what upper level could do with our internal location
521 // so we create a new one to return instead
522 final LttngLocation curLocation
= new LttngLocation(previousLocation
);
524 return new TmfContext(curLocation
, rank
);
528 public TmfContext
seekEvent(final double ratio
) {
529 // TODO Auto-generated method stub
534 public double getLocationRatio(final ITmfLocation
<?
> location
) {
535 // TODO Auto-generated method stub
540 * Return the event in the trace according to the given context. Read it if
543 * Similar (same?) as ParseEvent except that calling GetNext twice read the
544 * next one the second time.
546 * @param context Current TmfContext where to get the event
548 * @return The LttngEvent we read of null if no event are available
550 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
551 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
554 public int nbEventsRead
= 0;
557 public synchronized LttngEvent
getNext(final ITmfContext context
) {
560 System
.out
.println("getNextEvent(context) context.getLocation() -> " //$NON-NLS-1$
561 + context
.getLocation());
563 LttngEvent returnedEvent
= null;
564 LttngLocation curLocation
= null;
566 curLocation
= (LttngLocation
) context
.getLocation();
567 // If the location in context is null, create a new one
568 if (curLocation
== null)
569 curLocation
= getCurrentLocation(context
);
571 // *** Positioning trick :
572 // GetNextEvent only read the trace if :
573 // 1- The last operation was NOT a ParseEvent --> A read is required
575 // 2- The time of the previous location is different from the current
576 // one --> A seek + a read is required
577 if ((!(curLocation
.isLastOperationParse()))
578 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
579 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
581 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
582 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
583 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
584 seekEvent(curLocation
.getOperationTime());
586 // If the location is marked with the read next flag
587 // then it is pointing to the next event following the operation time
588 if (curLocation
.isLastOperationReadNext()) {
589 readNextEvent(curLocation
);
592 // Read the next event from the trace. The last one will NO LONGER
594 returnedEvent
= readNextEvent(curLocation
);
597 // No event was read, just return the one currently loaded (the last
599 returnedEvent
= currentLttngEvent
;
601 // Set the operation marker as read to both locations, to be able to
602 // detect we need to read the next event
603 previousLocation
.setLastOperationReadNext();
604 curLocation
.setLastOperationReadNext();
607 // If we read an event, set it's time to the locations (both previous
609 if (returnedEvent
!= null)
610 setPreviousAndCurrentTimes(context
, returnedEvent
, curLocation
);
612 return returnedEvent
;
615 // this method was extracted for profiling purposes
616 private synchronized void setPreviousAndCurrentTimes(final ITmfContext context
, final LttngEvent returnedEvent
,
617 final LttngLocation curLocation
) {
619 final ITmfTimestamp eventTimestamp
= returnedEvent
.getTimestamp();
620 // long eventTime = eventTimestamp.getValue();
621 previousLocation
.setOperationTime(eventTimestamp
.getValue());
622 curLocation
.setOperationTime(eventTimestamp
.getValue());
623 updateAttributes(context
, eventTimestamp
);
624 context
.increaseRank();
627 // this method was extracted for profiling purposes
628 private synchronized LttngEvent
readNextEvent(final LttngLocation curLocation
) {
629 LttngEvent returnedEvent
;
630 // Read the next event from the trace. The last one will NO LONGER BE
632 returnedEvent
= readEvent(curLocation
);
635 // Set the operation marker as read to both locations, to be able to
636 // detect we need to read the next event
637 previousLocation
.setLastOperationReadNext();
638 curLocation
.setLastOperationReadNext();
639 return returnedEvent
;
642 // this method was extracted for profiling purposes
643 private LttngLocation
getCurrentLocation(final ITmfContext context
) {
644 LttngLocation curLocation
;
645 curLocation
= new LttngLocation();
646 context
.setLocation(curLocation
);
651 * Return the event in the trace according to the given context. Read it if
654 * Similar (same?) as GetNextEvent except that calling ParseEvent twice will
655 * return the same event
657 * @param context Current TmfContext where to get the event
659 * @return The LttngEvent we read of null if no event are available
661 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngLocation
662 * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext
665 public synchronized LttngEvent
parseEvent(final ITmfContext context
) {
668 System
.out
.println("parseEvent(context) context.getLocation() -> " //$NON-NLS-1$
669 + context
.getLocation());
671 LttngEvent returnedEvent
= null;
672 LttngLocation curLocation
= null;
674 // If the location in context is null, create a new one
675 if (context
.getLocation() == null) {
676 curLocation
= new LttngLocation();
677 context
.setLocation(curLocation
);
679 curLocation
= (LttngLocation
) context
.getLocation();
682 // TMF assumes it is possible to read (GetNextEvent) to the next Event
683 // once ParseEvent() is called
684 // In LTTNG, there is not difference between "Parsing" and "Reading" an
686 // So, before "Parsing" an event, we have to make sure we didn't "Read"
688 // Also, "Reading" invalidate the previous Event in LTTNG and seek back
690 // so calling twice "Parse" will return the same event, giving a way to
691 // get the "Currently loaded" event
693 // *** Positionning trick :
694 // ParseEvent only read the trace if :
695 // 1- The last operation was NOT a ParseEvent --> A read is required
697 // 2- The time of the previous location is different from the current
698 // one --> A seek + a read is required
699 if (!curLocation
.isLastOperationParse()
700 || (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue())) {
701 // Previous time != Current time : We need to reposition to the
703 if (previousLocation
.getOperationTimeValue() != curLocation
.getOperationTimeValue()) {
705 System
.out
.println("\t\tSeeking in getNextEvent. [ LastTime : " //$NON-NLS-1$
706 + previousLocation
.getOperationTimeValue() + " CurrentTime" //$NON-NLS-1$
707 + curLocation
.getOperationTimeValue() + " ]"); //$NON-NLS-1$
708 seekEvent(curLocation
.getOperationTime());
711 // Read the next event from the trace. The last one will NO LONGER
713 returnedEvent
= readEvent(curLocation
);
715 // No event was read, just return the one currently loaded (the last
717 returnedEvent
= currentLttngEvent
;
719 // If we read an event, set it's time to the locations (both previous
721 if (returnedEvent
!= null) {
722 previousLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
723 curLocation
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
726 // Set the operation marker as parse to both location, to be able to
727 // detect we already "read" this event
728 previousLocation
.setLastOperationParse();
729 curLocation
.setLastOperationParse();
731 return returnedEvent
;
735 * Read the next event from the JNI and convert it as Lttng Event<p>
737 * @param location Current LttngLocation that to be updated with the event
740 * @return The LttngEvent we read of null if no event are available
742 * @see org.eclipse.linuxtools.lttng.event.LttngLocation
744 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
746 private synchronized LttngEvent
readEvent(final LttngLocation location
) {
747 LttngEvent returnedEvent
= null;
748 JniEvent tmpEvent
= null;
750 // Read the next event from JNI. THIS WILL INVALIDATE THE CURRENT LTTNG
752 tmpEvent
= currentJniTrace
.readNextEvent();
754 if (tmpEvent
!= null) {
756 // Convert will update the currentLttngEvent
757 returnedEvent
= convertJniEventToTmf(tmpEvent
);
759 location
.setOperationTime((LttngTimestamp
) returnedEvent
.getTimestamp());
761 location
.setOperationTime(getEndTime().getValue() + 1);
763 return returnedEvent
;
767 * Method to convert a JniEvent into a LttngEvent.
770 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent,
771 * boolean) with a default value for isParsingNeeded
773 * @param newEvent The JniEvent to convert into LttngEvent
775 * @return The converted LttngEvent
777 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
778 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
780 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent newEvent
) {
781 currentLttngEvent
= convertJniEventToTmf(newEvent
, IS_PARSING_NEEDED_DEFAULT
);
783 return currentLttngEvent
;
787 * Method to convert a JniEvent into a LttngEvent
789 * @param jniEvent The JniEvent to convert into LttngEvent
790 * @param isParsingNeeded A boolean value telling if the event should be
793 * @return The converted LttngEvent
795 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
796 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
798 public synchronized LttngEvent
convertJniEventToTmf(final JniEvent jniEvent
, final boolean isParsingNeeded
) {
803 // UNHACKED : We can no longer do that because TCF need to maintain
804 // several events at once.
805 // This is very slow to do so in LTTng, this has to be temporary.
807 // To save time here, we only set value instead of allocating new
809 // This give an HUGE performance improvement
810 // all allocation done in the LttngTrace constructor
812 eventTimestamp
.setValue(jniEvent
.getEventTime().getTime());
813 eventSource
= jniEvent
.requestEventSource();
815 eventType
= traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
));
817 final String fullTracePath
= getName();
818 final String reference
= fullTracePath
.substring(fullTracePath
.lastIndexOf('/') + 1);
819 currentLttngEvent
.setReference(reference
);
821 eventContent
.emptyContent();
823 currentLttngEvent
.setType(eventType
);
824 // Save the jni reference
825 currentLttngEvent
.updateJniEventReference(jniEvent
);
827 // Parse now if was asked
828 // Warning : THIS IS SLOW
830 eventContent
.getFields();
832 return currentLttngEvent
;
834 return convertJniEventToTmfMultipleEventEvilFix(jniEvent
, isParsingNeeded
);
839 * This method is a temporary fix to support multiple events at once in TMF
840 * This is expected to be slow and should be fixed in another way. See
841 * comment in convertJniEventToTmf();
843 * @param jniEvent The current JNI Event
844 * @return Current Lttng Event fully parsed
846 private synchronized LttngEvent
convertJniEventToTmfMultipleEventEvilFix(final JniEvent jniEvent
,
847 final boolean isParsingNeeded
) {
849 // Below : the "fix" with all the new and the full-parse
850 // Allocating new memory is slow.
851 // Parsing every events is very slow.
852 eventTimestamp
= new LttngTimestamp(jniEvent
.getEventTime().getTime());
853 eventSource
= jniEvent
.requestEventSource();
854 eventReference
= getName();
855 eventType
= new LttngEventType(traceTypes
.get(EventTypeKey
.getEventTypeHash(jniEvent
)));
856 eventContent
= new LttngEventContent(currentLttngEvent
);
857 currentLttngEvent
= new LttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
,
860 // The jni reference is no longer reliable but we will keep it anyhow
861 currentLttngEvent
.updateJniEventReference(jniEvent
);
862 // Ensure that the content is correctly set
863 eventContent
.setEvent(currentLttngEvent
);
865 // Parse the event if it was needed
867 // ONLY for testing, NOT parsing events with non-unique events WILL
868 // result in segfault in the JVM
870 eventContent
.getFields();
872 return currentLttngEvent
;
876 * Reference to the current LttngTrace we are reading from.
879 * Note : This bypass the framework and should not be use, except for
882 * @return Reference to the current LttngTrace
884 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
886 public JniTrace
getCurrentJniTrace() {
887 return currentJniTrace
;
891 * Return a reference to the current LttngEvent we have in memory.
893 * @return The current (last read) LttngEvent
895 * @see org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent
897 public synchronized LttngEvent
getCurrentEvent() {
898 return currentLttngEvent
;
902 * Get the major version number for the current trace
904 * @return Version major or -1 if unknown
906 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
909 public short getVersionMajor() {
910 if (currentJniTrace
!= null)
911 return currentJniTrace
.getLttMajorVersion();
917 * Get the minor version number for the current trace
919 * @return Version minor or -1 if unknown
921 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
924 public short getVersionMinor() {
925 if (currentJniTrace
!= null)
926 return currentJniTrace
.getLttMinorVersion();
932 * Get the number of CPU for this trace
934 * @return Number of CPU or -1 if unknown
936 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
939 public int getCpuNumber() {
940 if (currentJniTrace
!= null)
941 return currentJniTrace
.getCpuNumber();
947 public synchronized void dispose() {
948 if (currentJniTrace
!= null)
949 currentJniTrace
.closeTrace();
954 * Return a String identifying this trace.
956 * @return String that identify this trace
959 @SuppressWarnings("nls")
960 public String
toString() {
961 String returnedData
= "";
963 returnedData
+= "Path :" + getPath() + " ";
964 returnedData
+= "Trace:" + currentJniTrace
+ " ";
965 returnedData
+= "Event:" + currentLttngEvent
;
973 * EventTypeKey inner class
975 * This class is used to make the process of generating the HashMap key more
976 * transparent and so less error prone to use
978 final class EventTypeKey
{
981 // These two getEventTypeKey() functions should ALWAYS construct the key the
983 // Otherwise, every type search will fail!
985 // added final to encourage inlining.
987 // generating a hash code by hand to avoid a string creation
988 final static public int getEventTypeHash(final LttngEventType newEventType
) {
989 return generateHash(newEventType
.getTracefileName(), newEventType
.getCpuId(), newEventType
.getMarkerName());
992 final private static int generateHash(final String traceFileName
, final long cpuNumber
, final String markerName
) {
993 // 0x1337 is a prime number. The number of CPUs is always under 8192 on
994 // the current kernel, so this will work with the current linux kernel.
995 final int cpuHash
= (int) (cpuNumber
* (0x1337));
996 return traceFileName
.hashCode() ^
(cpuHash
) ^ markerName
.hashCode();
999 // generating a hash code by hand to avoid a string creation
1000 final static public int getEventTypeHash(final JniEvent newEvent
) {
1001 return generateHash(newEvent
.getParentTracefile().getTracefileName(), newEvent
.getParentTracefile()
1002 .getCpuNumber(), newEvent
.requestEventMarker().getName());