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