Monster fix: TMF model update + corresponding LTTng adaptations + JUnits
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng / src / org / eclipse / linuxtools / lttng / trace / LTTngTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * William Bourque (wbourque@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.lttng.trace;
14
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.Vector;
18
19 import org.eclipse.linuxtools.lttng.LttngException;
20 import org.eclipse.linuxtools.lttng.event.LttngEvent;
21 import org.eclipse.linuxtools.lttng.event.LttngEventContent;
22 import org.eclipse.linuxtools.lttng.event.LttngEventReference;
23 import org.eclipse.linuxtools.lttng.event.LttngEventSource;
24 import org.eclipse.linuxtools.lttng.event.LttngEventType;
25 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
26 import org.eclipse.linuxtools.lttng.jni.JniEvent;
27 import org.eclipse.linuxtools.lttng.jni.JniMarker;
28 import org.eclipse.linuxtools.lttng.jni.JniTime;
29 import org.eclipse.linuxtools.lttng.jni.JniTrace;
30 import org.eclipse.linuxtools.lttng.jni.JniTracefile;
31 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
32 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
33 import org.eclipse.linuxtools.tmf.trace.TmfTrace;
34 import org.eclipse.linuxtools.tmf.trace.TmfTraceContext;
35
36
37 class LTTngTraceException extends LttngException {
38 static final long serialVersionUID = -1636648737081868146L;
39
40 public LTTngTraceException(String errMsg) {
41 super(errMsg);
42 }
43 }
44
45 /**
46 * <b><u>LTTngTrace</u></b><p>
47 *
48 * LTTng trace implementation. It accesses the C trace handling library
49 * (seeking, reading and parsing) through the JNI component.
50 */
51 public class LTTngTrace extends TmfTrace {
52 private final static boolean SHOW_LTT_DEBUG_DEFAULT = false;
53 private final static boolean IS_PARSING_NEEDED_DEFAULT = false;
54 private final static int CHECKPOINT_PAGE_SIZE = 1;
55
56 // Reference to our JNI trace
57 private JniTrace currentJniTrace = null;
58
59 // *** HACK ***
60 // To save time, we will declare all component of the LttngEvent during the construction of the trace
61 // Then, while reading the trace, we will just SET the values instead of declaring new object
62 LttngTimestamp eventTimestamp = null;
63 LttngEventSource eventSource = null;
64 LttngEventType eventType = null;
65 LttngEventContent eventContent = null;
66 LttngEventReference eventReference = null;
67 // The actual event
68 LttngEvent currentLttngEvent = null;
69
70 // Hashmap of the possible types of events (Tracefile/CPU/Marker in the JNI)
71 HashMap<String, LttngEventType> traceTypes = null;
72 // This vector will be used to quickly find a marker name from a position
73 Vector<String> traceTypeNames = null;
74
75 /**
76 * Default Constructor.<p>
77 *
78 * @param path Path to a <b>directory</b> that contain an LTTng trace.
79 *
80 * @exception Exception (most likely LTTngTraceException or FileNotFoundException)
81 */
82 public LTTngTrace(String path) throws Exception {
83 // Call with "wait for completion" true and "skip indexing" false
84 this(path, true, false);
85 }
86
87 /**
88 * Constructor, with control over the indexing.
89 * <p>
90 * @param path Path to a <b>directory</b> that contain an LTTng trace.
91 * @param waitForCompletion Should we wait for indexign to complete before moving on.
92 *
93 * @exception Exception (most likely LTTngTraceException or FileNotFoundException)
94 */
95 public LTTngTrace(String path, boolean waitForCompletion) throws Exception {
96 // Call with "skip indexing" false
97 this(path, waitForCompletion, false);
98 }
99
100 /**
101 * Default constructor, with control over the indexing and possibility to bypass indexation
102 * <p>
103 * @param path Path to a <b>directory</b> that contain an LTTng trace.
104 * @param waitForCompletion Should we wait for indexign to complete before moving on.
105 * @param bypassIndexing Should we bypass indexing completly? This is should only be useful for unit testing.
106 *
107 * @exception Exception (most likely LTTngTraceException or FileNotFoundException)
108 *
109 */
110 public LTTngTrace(String path, boolean waitForCompletion, boolean bypassIndexing) throws Exception {
111 super(path, CHECKPOINT_PAGE_SIZE, true);
112 try {
113 currentJniTrace = new JniTrace(path, SHOW_LTT_DEBUG_DEFAULT);
114 }
115 catch (Exception e) {
116 throw new LTTngTraceException(e.getMessage());
117 }
118
119 // Set the start time of the trace
120 LttngTimestamp startTime = new LttngTimestamp(currentJniTrace.getStartTimeFromTimestampCurrentCounter().getTime());
121 setTimeRange(new TmfTimeRange(startTime, startTime));
122
123 // Export all the event types from the JNI side
124 traceTypes = new HashMap<String, LttngEventType>();
125 traceTypeNames = new Vector<String>();
126 initialiseEventTypes(currentJniTrace);
127
128 // *** VERIFY ***
129 // Verify that all those "default constructor" are safe to use
130 eventTimestamp = new LttngTimestamp();
131 eventSource = new LttngEventSource();
132 eventType = new LttngEventType();
133 eventContent = new LttngEventContent(currentLttngEvent);
134 eventReference = new LttngEventReference(this.getName());
135
136 // Create the skeleton event
137 currentLttngEvent = new LttngEvent(eventTimestamp, eventSource, eventType, eventContent, eventReference, null);
138
139 // Set the currentEvent to the eventContent
140 eventContent.setEvent(currentLttngEvent);
141
142 // Bypass indexing if asked
143 if ( bypassIndexing == false ) {
144 indexStream();
145 }
146 }
147
148 /*
149 * Copy constructor is forbidden for LttngEvenmStream
150 *
151 * Events are only valid for a very limited period of time and
152 * JNI library does not support multiple access at once (yet?).
153 * For this reason, copy constructor should NEVER be used.
154 */
155 private LTTngTrace(LTTngTrace oldStream) throws Exception {
156 super(null);
157 throw new Exception("Copy constructor should never be use with a LTTngTrace!");
158 }
159
160 /*
161 * Fill out the HashMap with "Type" (Tracefile/Marker)
162 *
163 * This should be called at construction once the trace is open
164 */
165 private void initialiseEventTypes(JniTrace trace) {
166 // Work variables
167 LttngEventType tmpType = null;
168 String[] markerFieldsLabels = null;
169
170 String newTracefileKey = null;
171 Integer newMarkerKey = null;
172
173 JniTracefile newTracefile = null;
174 JniMarker newMarker = null;
175
176 // First, obtain an iterator on TRACEFILES of owned by the TRACE
177 Iterator<String> tracefileItr = trace.getTracefilesMap().keySet().iterator();
178 while ( tracefileItr.hasNext() ) {
179 newTracefileKey = tracefileItr.next();
180 newTracefile = trace.getTracefilesMap().get(newTracefileKey);
181
182 // From the TRACEFILE read, obtain its MARKER
183 Iterator<Integer> markerItr = newTracefile.getTracefileMarkersMap().keySet().iterator();
184 while ( markerItr.hasNext() ) {
185 newMarkerKey = markerItr.next();
186 newMarker = newTracefile.getTracefileMarkersMap().get(newMarkerKey);
187
188 // From the MARKER we can obtain the MARKERFIELDS keys (i.e. labels)
189 markerFieldsLabels = newMarker.getMarkerFieldsHashMap().keySet().toArray( new String[newMarker.getMarkerFieldsHashMap().size()] );
190 tmpType = new LttngEventType(newTracefile.getTracefileName(), newTracefile.getCpuNumber(), newMarker.getName(), markerFieldsLabels );
191
192 // Add the type to the map/vector
193 addEventTypeToMap(tmpType);
194 }
195 }
196 }
197
198 /*
199 * Add a new type to the HashMap
200 *
201 * As the hashmap use a key format that is a bit dangerous to use, we should always add using this function.
202 */
203 private void addEventTypeToMap(LttngEventType newEventType) {
204 String newTypeKey = EventTypeKey.getEventTypeKey(newEventType);
205
206 this.traceTypes.put(newTypeKey, newEventType);
207 this.traceTypeNames.add(newTypeKey);
208 }
209
210 /**
211 * Return the next event in the trace.<p>
212 *
213 * @param context The actual context of the trace
214 *
215 * @return The next event, or null if none available
216 *
217 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
218 */
219 @Override
220 public LttngEvent parseEvent(TmfTraceContext context) {
221 JniEvent jniEvent;
222 LttngTimestamp timestamp = null;
223 LttngEvent returnedEvent = null;
224
225 synchronized (currentJniTrace) {
226 // Seek to the context's location
227 seekLocation(context.getLocation());
228
229 // Read an event from the JNI and convert it into a LttngEvent
230 jniEvent = currentJniTrace.readNextEvent();
231
232 //currentLttngEvent = (jniEvent != null) ? convertJniEventToTmf(jniEvent, true) : null;
233 if ( jniEvent != null ) {
234 currentLttngEvent = convertJniEventToTmf(jniEvent);
235 returnedEvent = currentLttngEvent;
236 }
237
238 // Save timestamp
239 timestamp = (LttngTimestamp) getCurrentLocation();
240 }
241 context.setLocation(timestamp);
242 context.setTimestamp(timestamp);
243 context.incrIndex();
244
245 return returnedEvent;
246 }
247
248 /**
249 * Method to convert a JniEvent into a LttngEvent.<p>
250 *
251 * Note : This method will call LttngEvent convertEventJniToTmf(JniEvent, boolean)
252 * with a default value for isParsingNeeded
253 *
254 * @param newEvent The JniEvent to convert into LttngEvent
255 *
256 * @return The converted LttngEvent
257 *
258 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
259 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
260 */
261 public LttngEvent convertJniEventToTmf(JniEvent newEvent) {
262 currentLttngEvent = convertJniEventToTmf(newEvent, IS_PARSING_NEEDED_DEFAULT);
263
264 return currentLttngEvent;
265 }
266
267 /**
268 * Method to convert a JniEvent into a LttngEvent
269 *
270 * @param jniEvent The JniEvent to convert into LttngEvent
271 * @param isParsingNeeded A boolean value telling if the event should be parsed or not.
272 *
273 * @return The converted LttngEvent
274 *
275 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniEvent
276 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
277 */
278 public LttngEvent convertJniEventToTmf(JniEvent jniEvent, boolean isParsingNeeded) {
279 // *** HACK ***
280 // To save time here, we only set value instead of allocating new object
281 // This give an HUGE performance improvement
282 // all allocation done in the LttngTrace constructor
283
284 eventTimestamp.setValue(jniEvent.getEventTime().getTime());
285 eventSource.setSourceId(jniEvent.requestEventSource());
286
287 eventType = traceTypes.get( EventTypeKey.getEventTypeKey(jniEvent) );
288
289 eventReference.setValue(jniEvent.getParentTracefile().getTracefilePath());
290 eventReference.setTracepath(this.getName());
291
292 // eventContent.setEvent(currentLttngEvent);
293 // eventContent.setType(eventType);
294 eventContent.emptyContent();
295
296 // currentLttngEvent.setContent(eventContent);
297 currentLttngEvent.setType(eventType);
298 // Save the jni reference
299 currentLttngEvent.setJniEventReference(jniEvent);
300
301 // Parse now if was asked
302 // Warning : THIS IS SLOW
303 if (isParsingNeeded == true ) {
304 eventContent.getFields();
305 }
306
307 return currentLttngEvent;
308 }
309
310 /**
311 * Seek (move) to a certain location in the trace.<p>
312 *
313 * WARNING : No event is read by this function, it just seek to a certain time.<br>
314 * Use "parseEvent()" or "getNextEvent()" to get the event we seeked to.
315 *
316 * @param location a TmfTimestamp of a position in the trace
317 *
318 * @return TmfTraceContext pointing the position in the trace at the seek location
319 */
320 public TmfTraceContext seekLocation(Object location) {
321
322 LttngTimestamp timestamp = null;
323
324 // If location is null, interpret this as a request to get back to the beginning of the trace
325 // in that case, just change the location, the seek will happen below
326 if (location == null) {
327 location = getStartTime();
328 }
329
330 if (location instanceof TmfTimestamp) {
331 long value = ((TmfTimestamp) location).getValue();
332 if (value != currentJniTrace.getCurrentEventTimestamp().getTime()) {
333 synchronized (currentJniTrace) {
334 currentJniTrace.seekToTime(new JniTime(value));
335 timestamp = (LttngTimestamp) getCurrentLocation();
336 }
337 }
338 }
339 else {
340 System.out.println("ERROR : Location not instance of TmfTimestamp");
341 }
342
343 // FIXME: LTTng hack - start
344 // return new TmfTraceContext(timestamp, timestamp, 0); // Original
345 return new TmfTraceContext(timestamp, timestamp, -1); // Hacked
346 // FIXME: LTTng hack - end
347 }
348
349 /**
350 * Location (timestamp) of our current position in the trace.<p>
351 *
352 * @return The time (in LttngTimestamp format) of the current event or AFTER endTime if no more event is available.
353 */
354 @Override
355 public Object getCurrentLocation() {
356
357 LttngTimestamp returnedLocation = null;
358 JniEvent tmpJniEvent = currentJniTrace.findNextEvent();
359
360 if ( tmpJniEvent != null ) {
361 returnedLocation = new LttngTimestamp(tmpJniEvent.getEventTime().getTime());
362 }
363 else {
364 returnedLocation = new LttngTimestamp( getEndTime().getValue() + 1 );
365 }
366
367 return returnedLocation;
368 }
369
370 /**
371 * Reference to the current LttngTrace we are reading from.<p>
372 *
373 * Note : This bypass the framework and should not be use, except for testing!
374 *
375 * @return Reference to the current LttngTrace
376 *
377 * @see org.eclipse.linuxtools.org.eclipse.linuxtools.lttng.jni.JniTrace
378 */
379 public JniTrace getCurrentJniTrace() {
380 return currentJniTrace;
381 }
382
383
384 /**
385 * Return a reference to the current LttngEvent we have in memory.
386 *
387 * @return The current (last read) LttngEvent
388 *
389 * @see org.eclipse.linuxtools.lttng.event.LttngEvent
390 */
391 public LttngEvent getCurrentEvent() {
392 return currentLttngEvent;
393 }
394
395
396 @Override
397 public String toString() {
398 String returnedData="";
399
400 returnedData += "Path :" + getPath() + " ";
401 returnedData += "Trace:" + currentJniTrace + " ";
402 returnedData += "Event:" + currentLttngEvent;
403
404 return returnedData;
405 }
406 }
407
408 /*
409 * EventTypeKey inner class
410 *
411 * This class is used to make the process of generating the HashMap key more transparent and so less error prone to use
412 *
413 */
414 class EventTypeKey {
415 //*** WARNING ***
416 // These two getEventTypeKey() functions should ALWAYS construct the key the same ways!
417 // Otherwise, every type search will fail!
418
419 static public String getEventTypeKey(LttngEventType newEventType) {
420 String key = newEventType.getTracefileName() + "/" + newEventType.getCpuId().toString() + "/" + newEventType.getMarkerName();
421
422 return key;
423 }
424
425 static public String getEventTypeKey(JniEvent newEvent) {
426 String key = newEvent.getParentTracefile().getTracefileName() + "/" + newEvent.getParentTracefile().getCpuNumber() + "/" + newEvent.requestEventMarker().getName();
427
428 return key;
429 }
430
431 }
This page took 0.039082 seconds and 5 git commands to generate.