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