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