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