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