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