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