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