[Bug304438] Improvement on ITmfLocation
[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 joie = 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 currentLocation = 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 currentLocation = 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 * Method to convert a JniEvent into a LttngEvent.<p>
233 *
234 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent, boolean)
235 * with a default value for isParsingNeeded
236 *
237 * @param newEvent The JniEvent to convert into LttngEvent
238 *
239 * @return The converted LttngEvent
240 *
241 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
242 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
243 */
244 public LttngEvent convertJniEventToTmf(JniEvent newEvent) {
245 currentLttngEvent = convertJniEventToTmf(newEvent, IS_PARSING_NEEDED_DEFAULT);
246
247 return currentLttngEvent;
248 }
249
250 /**
251 * Method to convert a JniEvent into a LttngEvent
252 *
253 * @param jniEvent The JniEvent to convert into LttngEvent
254 * @param isParsingNeeded A boolean value telling if the event should be parsed or not.
255 *
256 * @return The converted LttngEvent
257 *
258 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
259 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
260 */
261 public LttngEvent convertJniEventToTmf(JniEvent jniEvent, boolean isParsingNeeded) {
262 // *** HACK ***
263 // To save time here, we only set value instead of allocating new object
264 // This give an HUGE performance improvement
265 // all allocation done in the LttngTrace constructor
266
267 eventTimestamp.setValue(jniEvent.getEventTime().getTime());
268 eventSource.setSourceId(jniEvent.requestEventSource());
269
270 eventType = traceTypes.get( EventTypeKey.getEventTypeKey(jniEvent) );
271
272 eventReference.setValue(jniEvent.getParentTracefile().getTracefilePath());
273 eventReference.setTracepath(this.getName());
274
275 // eventContent.setEvent(currentLttngEvent);
276 // eventContent.setType(eventType);
277 eventContent.emptyContent();
278
279 // currentLttngEvent.setContent(eventContent);
280 currentLttngEvent.setType(eventType);
281 // Save the jni reference
282 currentLttngEvent.updateJniEventReference(jniEvent);
283
284 // Parse now if was asked
285 // Warning : THIS IS SLOW
286 if (isParsingNeeded == true ) {
287 eventContent.getFields();
288 }
289
290 return currentLttngEvent;
291 }
292
293 /**
294 * Reference to the current LttngTrace we are reading from.<p>
295 *
296 * Note : This bypass the framework and should not be use, except for testing!
297 *
298 * @return Reference to the current LttngTrace
299 *
300 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
301 */
302 public JniTrace getCurrentJniTrace() {
303 return currentJniTrace;
304 }
305
306
307 /**
308 * Return a reference to the current LttngEvent we have in memory.
309 *
310 * @return The current (last read) LttngEvent
311 *
312 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
313 */
314 public LttngEvent getCurrentEvent() {
315 return currentLttngEvent;
316 }
317
318 /**
319 * Get the major version number for the current trace
320 *
321 * @return Version major or -1 if unknown
322 *
323 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
324 *
325 */
326 public short getVersionMajor() {
327 if ( currentJniTrace!= null ) {
328 return currentJniTrace.getLttMajorVersion();
329 }
330 else {
331 return -1;
332 }
333 }
334
335 /**
336 * Get the minor version number for the current trace
337 *
338 * @return Version minor or -1 if unknown
339 *
340 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
341 *
342 */
343 public short getVersionMinor() {
344 if ( currentJniTrace!= null ) {
345 return currentJniTrace.getLttMinorVersion();
346 }
347 else {
348 return -1;
349 }
350 }
351
352 /**
353 * Get the number of CPU for this trace
354 *
355 * @return Number of CPU or -1 if unknown
356 *
357 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
358 *
359 */
360 public int getCpuNumber() {
361 if ( currentJniTrace!= null ) {
362 return currentJniTrace.getCpuNumber();
363 }
364 else {
365 return -1;
366 }
367 }
368
369
370 @Override
371 public String toString() {
372 String returnedData="";
373
374 returnedData += "Path :" + getPath() + " ";
375 returnedData += "Trace:" + currentJniTrace + " ";
376 returnedData += "Event:" + currentLttngEvent;
377
378 return returnedData;
379 }
380
381
382
383
384
385
386
387
388
389
390 public void bidon_function() {
391
392 System.out.println("START : " + getTimeRange().getStartTime().getValue());
393 System.out.println("END : " + getTimeRange().getEndTime().getValue());
394
395 for ( int pos=0; pos < fCheckpoints.size(); pos++) {
396 //for ( int pos=0; pos < 100; pos++) {
397 System.out.print(pos + ": " + "\t");
398 System.out.print( fCheckpoints.get(pos).getTimestamp() + "\t" );
399 System.out.println( fCheckpoints.get(pos).getLocation() );
400 }
401 }
402
403 @Override
404 public synchronized void indexTrace(boolean useless) {
405
406 // Position the trace at the beginning
407 TmfContext context = seekEvent( new LttngTimestamp(0L) );
408
409 long nbEvents=0L;
410 // joie = false;
411
412 LttngTimestamp startTime = null;
413 LttngTimestamp lastTime = new LttngTimestamp();
414
415 LttngEvent tmpEvent = (LttngEvent)getNextEvent(context);
416 LttngLocation tmpLocation = (LttngLocation)context.getLocation();
417
418
419 while ( tmpEvent != null) {
420 tmpLocation = (LttngLocation)context.getLocation();
421
422 if ( startTime == null ) {
423 startTime = new LttngTimestamp( tmpLocation.getCurrentTime() );
424 }
425
426 lastTime.setValue(tmpEvent.getTimestamp().getValue());
427
428 if ((nbEvents % getCacheSize()) == 0) {
429 LttngTimestamp tmpTimestamp = new LttngTimestamp( tmpLocation.getCurrentTime() );
430 LttngLocation newLocation = new LttngLocation( tmpLocation.getCurrentTime() );
431
432 fCheckpoints.add(new TmfCheckpoint(tmpTimestamp, newLocation ) );
433 }
434
435 nbEvents++;
436
437 tmpEvent = (LttngEvent)getNextEvent(context);
438 }
439
440 if (startTime != null) {
441 setTimeRange( new TmfTimeRange(startTime, lastTime) );
442 notifyListeners(getTimeRange() );
443 }
444
445 fNbEvents = nbEvents;
446 //bidon_function();
447 // joie = true;
448
449 }
450
451 @Override
452 public ITmfLocation<?> getCurrentLocation() {
453 return currentLocation;
454 }
455
456 @Override
457 public synchronized TmfContext seekLocation(ITmfLocation<?> location) {
458
459 if ( joie == true ) {
460 System.out.println("seekLocation(location) location -> " + location);
461 }
462
463 LttngTimestamp tmpTime = null;
464
465 if ( location == null ) {
466 tmpTime = (LttngTimestamp)getStartTime();
467 }
468 else {
469 // *** FIXME ***
470 // NEED TO AVOID TIMESTAMP CREATION
471 tmpTime = new LttngTimestamp( ((LttngLocation)location).getCurrentTime() );
472 }
473
474 // The only seek valid in LTTng is with the time, we call seekEvent(timestamp)
475 return seekEvent( tmpTime );
476 }
477
478 @Override
479 public synchronized TmfContext seekEvent(TmfTimestamp timestamp) {
480
481 if ( joie == true ) {
482 System.out.println("seekEvent(timestamp) timestamp -> " + timestamp);
483 }
484
485 currentJniTrace.seekToTime(new JniTime(timestamp.getValue()));
486
487 // Update the current time for the location
488 currentLocation.setCurrentTime( timestamp.getValue() );
489
490 return new TmfContext(currentLocation);
491 }
492
493 @Override
494 public synchronized TmfContext seekEvent(long position) {
495
496 if ( joie == true ) {
497 System.out.println("seekEvent(position) position -> " + position);
498 }
499
500 TmfTimestamp timestamp = null;
501 long index = position / getCacheSize();
502
503 if (fCheckpoints.size() > 0) {
504 if (index >= fCheckpoints.size()) {
505 index = fCheckpoints.size() - 1;
506 }
507 timestamp = (TmfTimestamp)fCheckpoints.elementAt((int)index).getTimestamp();
508 }
509 else {
510 timestamp = getStartTime();
511 }
512
513 TmfContext tmpContext = seekEvent(timestamp);
514 LttngLocation tmpLocation = (LttngLocation)tmpContext.getLocation();
515
516 Long currentPosition = index * getCacheSize();
517
518 JniEvent tmpJniEvent = currentJniTrace.findNextEvent();
519 while ( (tmpJniEvent != null) && ( currentPosition < position ) ) {
520 tmpJniEvent = currentJniTrace.readNextEvent();
521 currentPosition++;
522 tmpLocation.setCurrentTime( tmpJniEvent.getEventTime().getTime() );
523 }
524
525 return tmpContext;
526 }
527
528
529 @Override
530 public synchronized LttngEvent getNextEvent(TmfContext context) {
531
532 if ( joie == true ) {
533 System.out.println("getNextEvent(context) context.getLocation() -> " + context.getLocation());
534 }
535
536 LttngEvent returnedEvent = null;
537 LttngLocation tmpLocation = null;
538
539 if ( context.getLocation() == null ) {
540 tmpLocation = new LttngLocation();
541 context.setLocation(tmpLocation);
542 }
543 else {
544 tmpLocation = (LttngLocation)context.getLocation();
545 }
546
547 if ( tmpLocation.getCurrentTime() != currentJniTrace.getCurrentEventTimestamp().getTime() ) {
548 seekLocation( tmpLocation );
549 }
550
551 returnedEvent = readEvent(tmpLocation);
552
553 // No matter what happens, save the location
554 currentLocation = tmpLocation;
555
556 return returnedEvent;
557
558 }
559
560
561 @Override
562 public synchronized LttngEvent parseEvent(TmfContext context) {
563
564 if ( joie == true ) {
565 System.out.println("parseEvent(context) context.getLocation() -> " + context.getLocation());
566 }
567
568 LttngEvent returnedEvent = null;
569 LttngLocation tmpLocation = null;
570
571 if ( context.getLocation() == null ) {
572 tmpLocation = new LttngLocation();
573 context.setLocation(tmpLocation);
574 }
575 else {
576 tmpLocation = (LttngLocation)context.getLocation();
577 }
578
579 if ( tmpLocation.getCurrentTime() != currentJniTrace.getCurrentEventTimestamp().getTime() ) {
580 seekLocation( tmpLocation );
581 }
582
583 if ( currentLttngEvent.getTimestamp().getValue() != currentJniTrace.getCurrentEventTimestamp().getTime() ) {
584 returnedEvent = readEvent(tmpLocation);
585 }
586 else {
587 returnedEvent = currentLttngEvent;
588 }
589
590 // No matter what happens, save the location
591 currentLocation = tmpLocation;
592
593 return returnedEvent;
594
595 }
596
597
598 private synchronized LttngEvent readEvent(LttngLocation location) {
599 LttngEvent returnedEvent = null;
600 JniEvent tmpEvent = null;
601
602 tmpEvent = currentJniTrace.readNextEvent();
603
604 if ( tmpEvent != null ) {
605 // *** NOTE
606 // Convert will update the currentLttngEvent
607 returnedEvent = convertJniEventToTmf(tmpEvent);
608
609 // *** NOTE
610 // Set Last and Current time from the event read, as it could be different from the time requested
611 location.setLastReadTime(returnedEvent.getTimestamp().getValue() );
612 location.setCurrentTime( returnedEvent.getTimestamp().getValue() );
613 }
614 // *** NOTE
615 // If the read failed (likely the last event in the trace), set the LastReadTime to the JNI time
616 // That way, even if we try to read again, we will step over the bogus seek and read
617 else {
618 // location.setLastReadTime( currentJniTrace.getEndTime().getTime() + 1 );
619 // location.setCurrentTime( currentJniTrace.getEndTime().getTime() + 1 );
620 location.setLastReadTime( getEndTime().getValue() + 1 );
621 location.setCurrentTime( getEndTime().getValue() + 1 );
622 // location.setLastReadTime( Long.MAX_VALUE );
623 // location.setCurrentTime( Long.MAX_VALUE );
624 // location.setLastReadTime( currentJniTrace.getEndTime().getNanoSeconds() + 1 );
625 // location.setCurrentTime( currentJniTrace.getEndTime().getNanoSeconds() + 1 );
626 // System.out.println("TMF End time " + getEndTime().getValue() );
627 // System.out.println("JNI End time " + currentJniTrace.getEndTime().getTime() );
628 // System.out.println("JNI Partial time " + currentJniTrace.getEndTime().getNanoSeconds() );
629 }
630
631 return returnedEvent;
632 }
633
634
635 }
636
637 /*
638 * EventTypeKey inner class
639 *
640 * This class is used to make the process of generating the HashMap key more transparent and so less error prone to use
641 *
642 */
643 class EventTypeKey {
644 //*** WARNING ***
645 // These two getEventTypeKey() functions should ALWAYS construct the key the same ways!
646 // Otherwise, every type search will fail!
647
648 static public String getEventTypeKey(LttngEventType newEventType) {
649 String key = newEventType.getTracefileName() + "/" + newEventType.getCpuId().toString() + "/" + newEventType.getMarkerName();
650
651 return key;
652 }
653
654 static public String getEventTypeKey(JniEvent newEvent) {
655 String key = newEvent.getParentTracefile().getTracefileName() + "/" + newEvent.getParentTracefile().getCpuNumber() + "/" + newEvent.requestEventMarker().getName();
656
657 return key;
658 }
659
660 }
This page took 0.044624 seconds and 5 git commands to generate.