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