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