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