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