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