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