Commit | Line | Data |
---|---|---|
0152140d ASL |
1 | package org.eclipse.linuxtools.lttng.jni; |
2 | /******************************************************************************* | |
3 | * Copyright (c) 2009 Ericsson | |
4 | * | |
5 | * All rights reserved. This program and the accompanying materials are | |
6 | * made available under the terms of the Eclipse Public License v1.0 which | |
7 | * accompanies this distribution, and is available at | |
8 | * http://www.eclipse.org/legal/epl-v10.html | |
9 | * | |
10 | * Contributors: | |
11 | * William Bourque (wbourque@gmail.com) - Initial API and implementation | |
12 | *******************************************************************************/ | |
13 | ||
14 | import java.util.HashMap; | |
15 | import java.util.Iterator; | |
16 | import java.util.PriorityQueue; | |
17 | ||
18 | import org.eclipse.linuxtools.lttng.jni.common.JniTime; | |
c85e8cb2 | 19 | import org.eclipse.linuxtools.lttng.jni.common.Jni_C_Pointer_And_Library_Id; |
0152140d ASL |
20 | import org.eclipse.linuxtools.lttng.jni.exception.JniException; |
21 | import org.eclipse.linuxtools.lttng.jni.exception.JniOpenTraceFailedException; | |
22 | import org.eclipse.linuxtools.lttng.jni.exception.JniTraceException; | |
23 | import org.eclipse.linuxtools.lttng.jni.exception.JniTracefileWithoutEventException; | |
24 | ||
25 | /** | |
26 | * <b><u>JniTrace</u></b> | |
27 | * <p> | |
28 | * This is the top level class in the JNI. It provides access to the | |
29 | * LttTrace C structure in java. | |
30 | * <p> | |
31 | * Most important fields in the JniTrace are : | |
32 | * <ul> | |
33 | * <li>a JniTrace path (a trace <b>directory</b>) | |
34 | * <li>a HashMap of tracefiles that exists in this trace | |
35 | * </ul> | |
3b7509b0 WB |
36 | * <p> |
37 | * <b>NOTE</b><p> | |
38 | * This class is ABSTRACT, you need to extends it to support your specific LTTng version.<br> | |
39 | * Please look at the abstract functions to override at the bottom of this file.<p> | |
0152140d ASL |
40 | */ |
41 | public abstract class JniTrace extends Jni_C_Common { | |
42 | ||
43 | private final static boolean DEFAULT_LTT_DEBUG = false; | |
44 | ||
45 | // Internal C pointer of the JniTrace used in LTT | |
c85e8cb2 | 46 | private Jni_C_Pointer_And_Library_Id thisTracePtr = new Jni_C_Pointer_And_Library_Id(); |
0152140d ASL |
47 | |
48 | // Data we should populate from LTT | |
49 | // Note that all type have been scaled up as there is no "unsigned" in java | |
50 | // This might be a problem about "unsigned long" as there is no equivalent | |
51 | // in java | |
c357e4b6 | 52 | |
0152140d ASL |
53 | private String tracepath = ""; // Path of the trace. Should be a directory (like : /tmp/traceX) |
54 | private int cpuNumber = 0; | |
55 | private long archType = 0; | |
56 | private long archVariant = 0; | |
57 | private short archSize = 0; | |
58 | private short lttMajorVersion = 0; | |
59 | private short lttMinorVersion = 0; | |
60 | private short flightRecorder = 0; | |
61 | private long freqScale = 0; | |
62 | private long startFreq = 0; | |
63 | private long startTimestampCurrentCounter = 0; | |
64 | private long startMonotonic = 0; | |
65 | private JniTime startTimeNoAdjustement = null; | |
66 | private JniTime startTime = null; | |
67 | private JniTime endTime = null; | |
68 | ||
69 | // This Map holds a reference to the tracefiles owned by this trace | |
70 | private HashMap<String, JniTracefile> tracefilesMap = null; | |
71 | // The priority queue (similar to heap) hold events | |
72 | private PriorityQueue<JniEvent> eventsHeap = null; | |
73 | ||
74 | // This variable will hold the content of the "last" event we read | |
75 | private JniEvent currentEvent = null; | |
76 | ||
77 | // Should we print debug in the C library or not? | |
78 | private boolean printLttDebug = DEFAULT_LTT_DEBUG; | |
79 | ||
c85e8cb2 | 80 | |
0152140d | 81 | // This need to be called prior to any operation |
c85e8cb2 WB |
82 | protected native int ltt_initializeHandle(String libname); |
83 | ||
0152140d | 84 | // This need to be called at the very end (destructor) |
c85e8cb2 | 85 | protected native boolean ltt_freeHandle(int libId); |
0152140d ASL |
86 | |
87 | // Open/close native functions | |
c85e8cb2 WB |
88 | protected native long ltt_openTrace(int libId, String pathname, boolean printDebug); |
89 | protected native void ltt_closeTrace(int libId, long tracePtr); | |
0152140d ASL |
90 | |
91 | // Native access functions | |
c85e8cb2 WB |
92 | protected native String ltt_getTracepath(int libId, long tracePtr); |
93 | protected native int ltt_getCpuNumber(int libId, long tracePtr); | |
94 | protected native long ltt_getArchType(int libId, long tracePtr); | |
95 | protected native long ltt_getArchVariant(int libId, long tracePtr); | |
96 | protected native short ltt_getArchSize(int libId, long tracePtr); | |
97 | protected native short ltt_getLttMajorVersion(int libId, long tracePtr); | |
98 | protected native short ltt_getLttMinorVersion(int libId, long tracePtr); | |
99 | protected native short ltt_getFlightRecorder(int libId, long tracePtr); | |
100 | protected native long ltt_getFreqScale(int libId, long tracePtr); | |
101 | protected native long ltt_getStartFreq(int libId, long tracePtr); | |
102 | protected native long ltt_getStartTimestampCurrentCounter(int libId, long tracePtr); | |
103 | protected native long ltt_getStartMonotonic(int libId, long tracePtr); | |
0152140d ASL |
104 | |
105 | // Native function to fill out startTime | |
c85e8cb2 | 106 | protected native void ltt_feedStartTime(int libId, long tracePtr, JniTime startTime); |
0152140d ASL |
107 | |
108 | // Native function to fill out startTimeFromTimestampCurrentCounter | |
c85e8cb2 | 109 | protected native void ltt_feedStartTimeFromTimestampCurrentCounter(int libId, long tracePtr, JniTime startTime); |
0152140d ASL |
110 | |
111 | // Native function to fill out tracefilesMap | |
c85e8cb2 | 112 | protected native void ltt_feedAllTracefiles(int libId, long tracePtr); |
0152140d ASL |
113 | |
114 | // Native function to fill out the start and end time of the trace | |
c85e8cb2 | 115 | protected native void ltt_feedTracefileTimeRange(int libId, long tracePtr, JniTime startTime, JniTime endTime); |
0152140d ASL |
116 | |
117 | // Debug native function, ask LTT to print trace structure | |
c85e8cb2 | 118 | protected native void ltt_printTrace(int libId, long tracePtr); |
0152140d ASL |
119 | |
120 | /* | |
121 | * Default constructor is forbidden | |
122 | */ | |
123 | protected JniTrace() { | |
124 | } | |
125 | ||
126 | /** | |
127 | * Constructor that takes a tracepath parameter.<p> | |
128 | * | |
129 | * This constructor also opens the trace. | |
130 | * | |
131 | * @param newpath The <b>directory</b> of the trace to be opened | |
132 | * | |
133 | * @exception JniException | |
134 | */ | |
135 | public JniTrace(String newpath) throws JniException { | |
136 | this(newpath, DEFAULT_LTT_DEBUG); | |
137 | } | |
138 | ||
139 | /** | |
140 | * Constructor that takes a tracepath parameter and a debug value.<p> | |
141 | * | |
142 | * This constructor also opens the trace. | |
143 | * | |
144 | * @param newpath The <b>directory</b> of the trace to be opened | |
145 | * @param newPrintDebug Should the debug information be printed in the LTT C library | |
146 | * | |
147 | * @exception JniException | |
148 | */ | |
149 | public JniTrace(String newpath, boolean newPrintDebug) throws JniException { | |
150 | tracepath = newpath; | |
c85e8cb2 | 151 | thisTracePtr = new Jni_C_Pointer_And_Library_Id(); |
0152140d ASL |
152 | printLttDebug = newPrintDebug; |
153 | ||
154 | openTrace(newpath); | |
155 | } | |
156 | ||
157 | /** | |
158 | * Copy constructor. | |
159 | * | |
160 | * @param oldTrace A reference to the JniTrace to copy. | |
161 | */ | |
162 | public JniTrace(JniTrace oldTrace) { | |
163 | thisTracePtr = oldTrace.thisTracePtr; | |
164 | ||
165 | tracepath = oldTrace.tracepath; | |
166 | cpuNumber = oldTrace.cpuNumber; | |
167 | archType = oldTrace.archType; | |
168 | archVariant = oldTrace.archVariant; | |
169 | archSize = oldTrace.archSize; | |
170 | lttMajorVersion = oldTrace.lttMajorVersion; | |
171 | lttMinorVersion = oldTrace.lttMinorVersion; | |
172 | flightRecorder = oldTrace.flightRecorder; | |
173 | freqScale = oldTrace.freqScale; | |
174 | startFreq = oldTrace.startFreq; | |
175 | startTimestampCurrentCounter = oldTrace.startTimestampCurrentCounter; | |
176 | startMonotonic = oldTrace.startMonotonic; | |
177 | startTimeNoAdjustement = oldTrace.startTimeNoAdjustement; | |
178 | startTime = oldTrace.startTime; | |
179 | endTime = oldTrace.endTime; | |
180 | ||
181 | tracefilesMap = new HashMap<String, JniTracefile>(oldTrace.tracefilesMap.size()); | |
e0ea56dd | 182 | ltt_feedAllTracefiles(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); |
0152140d ASL |
183 | |
184 | eventsHeap = new PriorityQueue<JniEvent>( oldTrace.eventsHeap.size()); | |
e0ea56dd | 185 | populateEventHeap(); |
0152140d ASL |
186 | |
187 | printLttDebug = oldTrace.printLttDebug; | |
188 | } | |
189 | ||
190 | /** | |
191 | * Constructor, using C pointer.<p> | |
192 | * | |
193 | * @param newPtr The pointer to an already opened LttTrace C structure. | |
194 | * @param newPrintDebug Should the debug information be printed in the LTT C library | |
195 | * | |
196 | * @exception JniException | |
197 | * | |
c85e8cb2 | 198 | * @see org.eclipse.linuxtools.lttng.jni.common.Jni_C_Pointer_And_Library_Id |
0152140d | 199 | */ |
c85e8cb2 | 200 | public JniTrace(Jni_C_Pointer_And_Library_Id newPtr, boolean newPrintDebug) throws JniException { |
0152140d ASL |
201 | thisTracePtr = newPtr; |
202 | printLttDebug = newPrintDebug; | |
203 | ||
204 | // Populate our trace | |
205 | populateTraceInformation(); | |
206 | } | |
207 | ||
208 | ||
b9fb2d51 FC |
209 | @Override |
210 | public void finalize() { | |
0152140d ASL |
211 | // If the trace is open, close it |
212 | if (thisTracePtr.getPointer() != NULL) { | |
213 | closeTrace(); | |
214 | } | |
215 | ||
687cc7e7 | 216 | // Tell the C to free the allocated memory |
0152140d ASL |
217 | freeLibrary(); |
218 | } | |
219 | ||
220 | /** | |
221 | * Open an existing trace.<p> | |
222 | * | |
223 | * The tracepath is a directory and needs to exist, otherwise | |
a9fcdd8d | 224 | * a JafOpenTraceFailedException is throwed. |
0152140d ASL |
225 | * |
226 | * @param newPath The <b>directory</b> of the trace to be opened | |
227 | * | |
228 | * @exception JniOpenTraceFailedException Thrown if the open failed | |
229 | */ | |
230 | public void openTrace(String newPath) throws JniException { | |
231 | // If open is called while a trace is already opened, we will try to close it first | |
232 | if (thisTracePtr.getPointer() != NULL) { | |
233 | closeTrace(); | |
234 | } | |
235 | ||
236 | // Set the tracepath and open it | |
237 | tracepath = newPath; | |
238 | openTrace(); | |
239 | } | |
240 | ||
241 | /** | |
242 | * Open an existing trace.<p> | |
243 | * | |
244 | * The tracepath should have been set already, | |
245 | * | |
246 | * @exception JniOpenTraceFailedException Thrown if the open failed | |
247 | */ | |
248 | public void openTrace() throws JniException { | |
249 | ||
250 | // Raise an exception if the tracepath is empty, otherwise open the trace | |
251 | if (tracepath == "") { | |
252 | throw new JniTraceException("Tracepath is not set. (openTrace)"); | |
253 | } | |
254 | ||
255 | // If the file is already opened, close it first | |
256 | if (thisTracePtr.getPointer() != NULL) { | |
257 | closeTrace(); | |
258 | } | |
259 | ||
c85e8cb2 WB |
260 | // Initialization of the library is made here |
261 | // It is very important that the id is kept! | |
262 | int newLibraryId = initializeLibrary(); | |
263 | if ( newLibraryId != -1 ) { | |
0152140d | 264 | // Call the LTT to open the trace |
c85e8cb2 WB |
265 | // Note that the libraryId is not yet and the pointer |
266 | long newPtr = ltt_openTrace(newLibraryId, tracepath, printLttDebug); | |
0152140d ASL |
267 | |
268 | if (newPtr == NULL) { | |
c85e8cb2 | 269 | thisTracePtr = new Jni_C_Pointer_And_Library_Id(); |
0152140d ASL |
270 | throw new JniOpenTraceFailedException("Error while opening trace. Is the tracepath correct? (openTrace)"); |
271 | } | |
272 | ||
273 | // This is OUR pointer | |
c85e8cb2 | 274 | thisTracePtr = new Jni_C_Pointer_And_Library_Id(newLibraryId, newPtr); |
0152140d ASL |
275 | |
276 | // Populate the trace with LTT information | |
277 | populateTraceInformation(); | |
278 | } | |
279 | else { | |
c85e8cb2 | 280 | thisTracePtr = new Jni_C_Pointer_And_Library_Id(); |
687cc7e7 WB |
281 | throw new JniTraceException("Failed to initialize library! Is the trace version supported?\n" + |
282 | "Make sure you have the correct LTTv library compiled. (openTrace)"); | |
0152140d ASL |
283 | } |
284 | } | |
285 | ||
286 | /** | |
287 | * Close a trace.<p> | |
288 | * | |
289 | * If the trace is already closed, will silently do nothing. | |
290 | */ | |
291 | public void closeTrace() { | |
292 | ||
293 | if (thisTracePtr.getPointer() != NULL) { | |
c85e8cb2 | 294 | ltt_closeTrace(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); |
0152140d ASL |
295 | |
296 | // Clear the tracefile map | |
297 | tracefilesMap.clear(); | |
298 | tracefilesMap = null; | |
299 | ||
300 | // Clear the eventsHeap and make it points to null | |
301 | eventsHeap.clear(); | |
302 | eventsHeap = null; | |
303 | ||
304 | // Nullify the pointer | |
c85e8cb2 | 305 | thisTracePtr = new Jni_C_Pointer_And_Library_Id(); |
0152140d ASL |
306 | } |
307 | } | |
308 | ||
309 | /** | |
310 | * This function force the library to free its memory.<p> | |
311 | * | |
312 | * Note : No call to the library will work after this until ltt_initializeHandle is called again | |
313 | */ | |
314 | public void freeLibrary() { | |
c85e8cb2 | 315 | ltt_freeHandle(thisTracePtr.getLibraryId()); |
0152140d ASL |
316 | } |
317 | ||
318 | /* | |
319 | * This function populates the trace data with data from LTT | |
320 | * | |
321 | * @throws JniException | |
322 | */ | |
323 | private void populateTraceInformation() throws JniException { | |
324 | if (thisTracePtr.getPointer() == NULL) { | |
325 | throw new JniTraceException("Pointer is NULL, trace not opened/already closed? (populateTraceInformation)"); | |
326 | } | |
327 | ||
328 | // Populate from the LTT library | |
c85e8cb2 WB |
329 | tracepath = ltt_getTracepath(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); |
330 | cpuNumber = ltt_getCpuNumber(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
331 | archType = ltt_getArchType(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
332 | archVariant = ltt_getArchVariant(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
333 | archSize = ltt_getArchSize(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
334 | lttMajorVersion = ltt_getLttMajorVersion(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
335 | lttMinorVersion = ltt_getLttMinorVersion(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
336 | flightRecorder = ltt_getFlightRecorder(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
337 | freqScale = ltt_getFreqScale(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
338 | startFreq = ltt_getStartFreq(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
339 | startTimestampCurrentCounter = ltt_getStartTimestampCurrentCounter(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
340 | startMonotonic = ltt_getStartMonotonic(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); | |
0152140d ASL |
341 | |
342 | // Creation of time is a bit different, we need to pass the object reference to C | |
343 | // | |
344 | // *** NOTE : LTTv consider "raw startTime" (time without any frequency adjustement) to be default startTime | |
345 | // So "startTimeNoAdjustement" is obtain throught "ltt_feedStartTime()" and | |
346 | // "startTime" is obtained from ltt_feedStartTimeFromTimestampCurrentCounter() | |
347 | startTimeNoAdjustement = new JniTime(); | |
c85e8cb2 | 348 | ltt_feedStartTime(thisTracePtr.getLibraryId(), thisTracePtr.getPointer(), startTimeNoAdjustement); |
0152140d ASL |
349 | |
350 | startTime = new JniTime(); | |
c85e8cb2 | 351 | ltt_feedStartTimeFromTimestampCurrentCounter(thisTracePtr.getLibraryId(), thisTracePtr.getPointer(), startTime); |
0152140d ASL |
352 | |
353 | // Call the fill up function for the tracefiles map | |
354 | if ( tracefilesMap== null ) { | |
355 | tracefilesMap = new HashMap<String, JniTracefile>(); | |
356 | } | |
c85e8cb2 | 357 | ltt_feedAllTracefiles(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); |
0152140d ASL |
358 | |
359 | // Now, obtain the trace "endTime" | |
360 | // Note that we discard "startTime" right away, as we already have it | |
361 | endTime = new JniTime(); | |
c85e8cb2 | 362 | ltt_feedTracefileTimeRange(thisTracePtr.getLibraryId(), thisTracePtr.getPointer(), new JniTime(), endTime); |
0152140d ASL |
363 | |
364 | if (eventsHeap == null) { | |
365 | eventsHeap = new PriorityQueue<JniEvent>(tracefilesMap.size()); | |
366 | } | |
367 | ||
368 | // Populate the heap with events | |
369 | populateEventHeap(); | |
370 | } | |
371 | ||
372 | /* | |
373 | * This function populates the event heap with one event from each tracefile | |
374 | * It should be called after each seek or when the object is constructed | |
375 | */ | |
376 | private void populateEventHeap() { | |
377 | currentEvent = null; | |
378 | eventsHeap.clear(); | |
379 | ||
380 | Object new_key = null; | |
381 | JniTracefile tmpTracefile = null; | |
382 | ||
383 | Iterator<String> iterator = tracefilesMap.keySet().iterator(); | |
384 | while( iterator.hasNext() ) { | |
385 | new_key = iterator.next(); | |
386 | ||
387 | tmpTracefile = tracefilesMap.get(new_key); | |
388 | if ( tmpTracefile.getCurrentEvent().getEventState() == EOK ) { | |
389 | eventsHeap.add( tmpTracefile.getCurrentEvent() ); | |
390 | } | |
391 | } | |
392 | } | |
393 | ||
394 | /* | |
395 | * Fills a map of all the trace files. | |
396 | * | |
397 | * Note: This function is called from C and there is no way to propagate | |
398 | * exception back to the caller without crashing JNI. Therefore, it MUST | |
399 | * catch all exceptions. | |
400 | * | |
401 | * @param tracefileName | |
402 | * @param tracefilePtr | |
403 | */ | |
404 | protected void addTracefileFromC(String tracefileName, long tracefilePtr) { | |
405 | ||
406 | JniTracefile newTracefile = null; | |
407 | ||
408 | // Create a new tracefile object and insert it in the map | |
409 | // the tracefile fill itself with LTT data while being constructed | |
410 | try { | |
c85e8cb2 | 411 | newTracefile = allocateNewJniTracefile(new Jni_C_Pointer_And_Library_Id(thisTracePtr.getLibraryId(), tracefilePtr), this); |
0152140d ASL |
412 | getTracefilesMap().put( (tracefileName + newTracefile.getCpuNumber()), newTracefile); |
413 | } | |
414 | catch(JniTracefileWithoutEventException e) { | |
415 | if ( printLttDebug == true ) { | |
c85e8cb2 | 416 | printlnC(thisTracePtr.getLibraryId(), "JniTracefile " + tracefileName + " has no event (addTracefileFromC). Ignoring."); |
0152140d ASL |
417 | } |
418 | } | |
419 | catch(Exception e) { | |
420 | if ( printLttDebug == true ) { | |
c85e8cb2 | 421 | printlnC(thisTracePtr.getLibraryId(), "Failed to add tracefile " + tracefileName + " to tracefilesMap!(addTracefileFromC)\n\tException raised : " + e.toString() ); |
0152140d ASL |
422 | } |
423 | } | |
424 | } | |
425 | ||
426 | /** | |
427 | * Return the top event in the events stack, determined by timestamp, in the trace (all the tracefiles).<p> | |
428 | * | |
429 | * Note : If the events were read before, the top event and the event currently loaded (currentEvent) are most likely the same. | |
430 | * | |
431 | * @return The top event in the stack or null if no event is available. | |
432 | * | |
c357e4b6 | 433 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent |
0152140d ASL |
434 | */ |
435 | public JniEvent findNextEvent() { | |
436 | return eventsHeap.peek(); | |
437 | } | |
438 | ||
439 | /** | |
440 | * Return the next event in the events stack, determined by timestamp, in the trace (all the tracefiles).<p> | |
441 | * | |
442 | * @return The next event in the trace or null if no event is available. | |
443 | * | |
c357e4b6 | 444 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent |
0152140d ASL |
445 | */ |
446 | public JniEvent readNextEvent() { | |
447 | // Get the "next" event on the top of the heap but DO NOT remove it | |
448 | JniEvent tmpEvent = eventsHeap.peek(); | |
449 | ||
450 | // If the event is null, it was the last one in the trace we can leave the function | |
451 | if (tmpEvent == null) { | |
452 | return null; | |
453 | } | |
454 | ||
455 | // Otherwise, we need to make sure the timestamp of the event we got is not the same as the last "NextEvent" we requested | |
456 | // NOTE : JniEvent.compareTo() compare by timestamp AND type, as 2 events of different type could have the same timestamp. | |
457 | if ( tmpEvent.compareTo(currentEvent) == 0 ) { | |
458 | // Remove the event on top as it is the same currentEventTimestamp | |
459 | eventsHeap.poll(); | |
460 | ||
461 | // Read the next event for this particular event type | |
462 | tmpEvent.readNextEvent(); | |
463 | ||
464 | // If the event state is sane (not Out of Range), put it back in the heap | |
465 | if ( tmpEvent.getEventState() == EOK ) { | |
466 | eventsHeap.add(tmpEvent); | |
467 | } | |
468 | ||
469 | // Pick the top event again | |
470 | tmpEvent = eventsHeap.peek(); | |
471 | ||
472 | // Save the event we just read as the "current event" | |
473 | currentEvent = tmpEvent; | |
474 | } | |
475 | // If the event on top has different timestamp than the currentTimestamp, just save this timestamp as current | |
476 | else { | |
477 | currentEvent = tmpEvent; | |
478 | } | |
479 | ||
480 | return tmpEvent; | |
481 | } | |
482 | ||
483 | /** | |
484 | * Read the next event on a certain tracefile.<p> | |
485 | * | |
486 | * By calling this function make sure the "global" readNextEvent() stay synchronised. | |
487 | * Calling readNextEvent() after this function will consider this tracefile moved and is then consistent. | |
488 | * | |
489 | * @param targetTracefile The tracefile object to read from | |
490 | * | |
491 | * @return The next event in the tracefile or null if no event is available. | |
492 | * | |
c357e4b6 WB |
493 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile |
494 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent | |
0152140d ASL |
495 | */ |
496 | public JniEvent readNextEvent(JniTracefile targetTracefile) { | |
497 | JniEvent returnedEvent = null; | |
498 | ||
499 | // There is 2 special cases where we should read the CURRENT event, not the next one | |
500 | // 1- The currentEvent is null --> We never read or we just seeked | |
501 | // 2- The currentEvent is of another type --> We last read on a DIFFERENT tracefile | |
502 | if ( (currentEvent == null) || | |
503 | (currentEvent.getParentTracefile().equals(targetTracefile) == false) | |
504 | ) { | |
505 | returnedEvent = targetTracefile.getCurrentEvent(); | |
506 | // Save the event we read | |
507 | currentEvent = returnedEvent; | |
508 | } | |
509 | else { | |
510 | // Remove from the event related to this tracefile from the event heap, if it exists. | |
511 | // WARNING : This only safe as long getCurrentEvent() never return "null" in any case. | |
512 | eventsHeap.remove(targetTracefile.getCurrentEvent() ); | |
513 | ||
514 | // If status EOK, we can return the event, otherwise something wrong happen (out of range, read error, etc...) | |
515 | if ( targetTracefile.readNextEvent() == EOK) { | |
516 | returnedEvent = targetTracefile.getCurrentEvent(); | |
517 | // Add back to the heap the read event | |
518 | eventsHeap.add(returnedEvent); | |
519 | } | |
520 | // Save the event we read... | |
521 | // Note : might be null if the read failed and it's ok | |
522 | currentEvent = targetTracefile.getCurrentEvent(); | |
523 | } | |
524 | ||
525 | return returnedEvent; | |
526 | } | |
527 | ||
528 | /** | |
529 | * Seek to a certain time but <b>do not</b> read the next event.<p> | |
530 | * | |
531 | * This only position the trace, it will not return anything.<p> | |
532 | * | |
533 | * @param seekTime The time where we want to seek to | |
534 | * | |
c357e4b6 | 535 | * @see org.eclipse.linuxtools.lttng.jni.common.JniTime |
0152140d ASL |
536 | */ |
537 | public void seekToTime(JniTime seekTime) { | |
538 | ||
539 | // Invalidate the last read event | |
540 | currentEvent = null; | |
541 | ||
542 | Object tracefile_name = null; | |
543 | Iterator<String> iterator = tracefilesMap.keySet().iterator(); | |
544 | ||
545 | while (iterator.hasNext() ) { | |
546 | // We seek to the given event for ALL tracefiles | |
547 | tracefile_name = iterator.next(); | |
548 | seekToTime(seekTime, tracefilesMap.get(tracefile_name)); | |
549 | } | |
550 | ||
551 | populateEventHeap(); | |
552 | } | |
553 | ||
554 | /** | |
555 | * Seek to a certain time on a certain tracefile but <b>do not</b> read the next event.<p> | |
556 | * | |
557 | * This only position the trace, it will not return anything.<p> | |
558 | * | |
559 | * @param targetTracefile The tracefile object to read from | |
560 | * @param seekTime The time where we want to seek to | |
561 | * | |
c357e4b6 WB |
562 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile |
563 | * @see org.eclipse.linuxtools.lttng.jni.common.JniTime | |
0152140d ASL |
564 | */ |
565 | public void seekToTime(JniTime seekTime, JniTracefile targetTracefile) { | |
566 | // Invalidate the current read event | |
567 | currentEvent = null; | |
568 | ||
569 | // Remove from the event related to this tracefile from the event heap, if it exists. | |
570 | // WARNING : This is only safe as long getCurrentEvent() never return "null" in any case. | |
571 | eventsHeap.remove(targetTracefile.getCurrentEvent() ); | |
572 | ||
573 | // Perform the actual seek on the tracefile | |
574 | // Add the event to the heap if it succeed | |
575 | if ( targetTracefile.seekToTime(seekTime) == EOK) { | |
576 | // Add back to the heap the read event | |
577 | eventsHeap.add(targetTracefile.getCurrentEvent()); | |
578 | } | |
579 | } | |
580 | ||
581 | /** | |
582 | * Seek to a certain timestamp and read the next event. | |
583 | * <p> | |
584 | * If no more events are available or an error happen, null will be returned. | |
585 | * | |
586 | * @param seekTime The time where we want to seek to. | |
587 | * | |
588 | * @return The event just after the seeked time or null if none available. | |
589 | * | |
c357e4b6 WB |
590 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent |
591 | * @see org.eclipse.linuxtools.lttng.jni.common.JniTime | |
0152140d ASL |
592 | */ |
593 | public JniEvent seekAndRead(JniTime seekTime) { | |
594 | JniEvent returnedEvent = null; | |
595 | seekToTime(seekTime); | |
596 | ||
597 | // The trace should be correctly positionned, let's get the event | |
598 | returnedEvent = readNextEvent(); | |
599 | ||
600 | return returnedEvent; | |
601 | } | |
602 | ||
603 | /** | |
604 | * Seek to a certain timestamp on a certain tracefile and read the next event.<p> | |
605 | * | |
606 | * If no more events are available or an error happen, null will be returned. | |
607 | * | |
608 | * Calling readNextEvent() after this function will consider this tracefile moved and is then consistent.<br> | |
609 | * | |
c357e4b6 | 610 | * @param targetTracefile The tracefile object to read from |
0152140d ASL |
611 | * @param seekTime The time where we want to seek to |
612 | * | |
613 | * @return The event just after the seeked time or null if none available. | |
614 | * | |
c357e4b6 WB |
615 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile |
616 | * @see org.eclipse.linuxtools.lttng.jni.common.JniTime | |
617 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent | |
0152140d ASL |
618 | */ |
619 | public JniEvent seekAndRead(JniTime seekTime, JniTracefile targetTracefile) { | |
620 | seekToTime(seekTime, targetTracefile); | |
621 | return readNextEvent(targetTracefile); | |
622 | } | |
623 | ||
624 | /** | |
625 | * Get a certain tracefile from its given name.<p> | |
626 | * | |
627 | * @param tracefileName The name of the tracefile. | |
628 | * | |
629 | * @return The tracefile found or null if none. | |
630 | * | |
c357e4b6 | 631 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile |
0152140d ASL |
632 | */ |
633 | public JniTracefile requestTracefileByName(String tracefileName) { | |
634 | return tracefilesMap.get(tracefileName); | |
635 | } | |
636 | ||
637 | /** | |
638 | * Get a certain event associated to a tracefile from the tracefile name.<p> | |
639 | * | |
640 | * @param tracefileName The name of the trace file. | |
641 | * | |
642 | * @return Event of the tracefile or null if none found. | |
643 | * | |
c357e4b6 | 644 | * @see org.eclipse.linuxtools.lttng.jni.JniEvent |
0152140d ASL |
645 | */ |
646 | public JniEvent requestEventByName(String tracefileName) { | |
647 | JniEvent returnValue = null; | |
648 | ||
649 | JniTracefile tmpTracefile = tracefilesMap.get(tracefileName); | |
650 | ||
651 | // If the tracefile is found, return the current event | |
652 | // There should always be an event linked to a tracefile | |
653 | if (tmpTracefile != null) { | |
654 | returnValue = tmpTracefile.getCurrentEvent(); | |
655 | } | |
656 | ||
657 | return returnValue; | |
658 | } | |
659 | ||
660 | // Access to class variable. Most of them doesn't have setter | |
661 | public String getTracepath() { | |
662 | return tracepath; | |
663 | } | |
664 | ||
665 | public int getCpuNumber() { | |
666 | return cpuNumber; | |
667 | } | |
668 | ||
669 | public long getArchType() { | |
670 | return archType; | |
671 | } | |
672 | ||
673 | public long getArchVariant() { | |
674 | return archVariant; | |
675 | } | |
676 | ||
677 | public short getArchSize() { | |
678 | return archSize; | |
679 | } | |
680 | ||
681 | public short getLttMajorVersion() { | |
682 | return lttMajorVersion; | |
683 | } | |
684 | ||
685 | public short getLttMinorVersion() { | |
686 | return lttMinorVersion; | |
687 | } | |
688 | ||
689 | public short getFlightRecorder() { | |
690 | return flightRecorder; | |
691 | } | |
692 | ||
693 | public long getFreqScale() { | |
694 | return freqScale; | |
695 | } | |
696 | ||
697 | public long getStartFreq() { | |
698 | return startFreq; | |
699 | } | |
700 | ||
701 | public long getStartTimestampCurrentCounter() { | |
702 | return startTimestampCurrentCounter; | |
703 | } | |
704 | ||
705 | public long getStartMonotonic() { | |
706 | return startMonotonic; | |
707 | } | |
708 | ||
709 | public JniTime getStartTime() { | |
710 | return startTime; | |
711 | } | |
712 | ||
713 | public JniTime getEndTime() { | |
714 | return endTime; | |
715 | } | |
716 | ||
717 | public JniTime getStartTimeNoAdjustement() { | |
718 | return startTimeNoAdjustement; | |
719 | } | |
720 | ||
721 | public HashMap<String, JniTracefile> getTracefilesMap() { | |
722 | return tracefilesMap; | |
723 | } | |
724 | ||
725 | /** | |
726 | * The timestamp of the last read event.<p> | |
727 | * | |
728 | * Note : If no event is available, Long.MAX_VALUE is returned. | |
729 | * | |
730 | * @return Time of the last event read | |
731 | * | |
c357e4b6 | 732 | * @see org.eclipse.linuxtools.lttng.jni.common.JniTime |
0152140d ASL |
733 | */ |
734 | public JniTime getCurrentEventTimestamp() { | |
735 | JniTime returnedTime = null; | |
736 | ||
737 | // If no event were read or we reach the last event in the trace, | |
738 | // currentEvent will be null | |
739 | if ( currentEvent != null ) { | |
740 | returnedTime = currentEvent.getEventTime(); | |
741 | } | |
742 | else { | |
743 | returnedTime = new JniTime(Long.MAX_VALUE); | |
744 | } | |
745 | return returnedTime; | |
746 | } | |
747 | ||
748 | /** | |
749 | * Pointer to the LttTrace C structure.<p> | |
750 | * | |
751 | * The pointer should only be used <u>INTERNALY</u>, do not use unless you | |
752 | * know what you are doing. | |
753 | * | |
754 | * @return The actual (long converted) pointer or NULL. | |
755 | * | |
c85e8cb2 | 756 | * @see org.eclipse.linuxtools.lttng.jni.common.Jni_C_Pointer_And_Library_Id |
0152140d | 757 | */ |
c85e8cb2 | 758 | public Jni_C_Pointer_And_Library_Id getTracePtr() { |
0152140d ASL |
759 | return thisTracePtr; |
760 | } | |
761 | ||
762 | /** | |
763 | * Return boolean value saying if the debug is enabled in LTT or not.<p> | |
764 | * | |
765 | * Note : this need to be set at construction. | |
766 | * | |
767 | * @return If the debug is set or not | |
768 | */ | |
769 | public boolean isPrintingLttDebug() { | |
770 | return printLttDebug; | |
771 | } | |
772 | ||
773 | /** | |
774 | * Print information for all the tracefiles associated with this trace. | |
775 | * <u>Intended to debug</u><p> | |
776 | * | |
777 | * This function will call Ltt to print, so information printed will be the | |
778 | * one from the C structure, not the one populated in java. | |
779 | * | |
c357e4b6 | 780 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile |
0152140d ASL |
781 | */ |
782 | public void printAllTracefilesInformation() { | |
783 | JniTracefile tracefile = null; | |
784 | ||
785 | Iterator<String> iterator = tracefilesMap.keySet().iterator(); | |
786 | while (iterator.hasNext()) { | |
787 | tracefile = tracefilesMap.get(iterator.next()); | |
788 | tracefile.printTracefileInformation(); | |
789 | } | |
790 | } | |
791 | ||
792 | /** | |
793 | * Print information for this trace. | |
794 | * <u>Intended to debug</u><p> | |
795 | * | |
796 | * This function will call Ltt to print, so information printed will be the | |
797 | * one from the C structure, not the one populated in java.<p> | |
798 | */ | |
799 | public void printTraceInformation() { | |
c85e8cb2 | 800 | ltt_printTrace(thisTracePtr.getLibraryId(), thisTracePtr.getPointer()); |
0152140d ASL |
801 | } |
802 | ||
803 | /** | |
804 | * toString() method. | |
805 | * <u>Intended to debug</u><br> | |
806 | * | |
807 | * @return Attributes of the object concatenated in String | |
808 | */ | |
809 | @Override | |
810 | public String toString() { | |
811 | String returnData = ""; | |
812 | returnData += "tracepath : " + tracepath + "\n"; | |
813 | returnData += "cpuNumber : " + cpuNumber + "\n"; | |
814 | returnData += "archType : " + archType + "\n"; | |
815 | returnData += "archVariant : " + archVariant + "\n"; | |
816 | returnData += "archSize : " + archSize + "\n"; | |
817 | returnData += "lttMajorVersion : " + lttMajorVersion + "\n"; | |
818 | returnData += "lttMinorVersion : " + lttMinorVersion + "\n"; | |
819 | returnData += "flightRecorder : " + flightRecorder + "\n"; | |
820 | returnData += "freqScale : " + freqScale + "\n"; | |
821 | returnData += "startFreq : " + startFreq + "\n"; | |
822 | returnData += "startTimestampCurrentCounter : " + startTimestampCurrentCounter + "\n"; | |
823 | returnData += "startMonotonic : " + startMonotonic + "\n"; | |
824 | returnData += "startTimeNoAdjustement : " + startTimeNoAdjustement.getReferenceToString() + "\n"; | |
825 | returnData += " seconds : " + startTimeNoAdjustement.getSeconds() + "\n"; | |
826 | returnData += " nanoSeconds : " + startTimeNoAdjustement.getNanoSeconds() + "\n"; | |
827 | returnData += "startTime : " + startTime.getReferenceToString() + "\n"; | |
828 | returnData += " seconds : " + startTime.getSeconds() + "\n"; | |
829 | returnData += " nanoSeconds : " + startTime.getNanoSeconds() + "\n"; | |
830 | returnData += "endTime : " + endTime.getReferenceToString() + "\n"; | |
831 | returnData += " seconds : " + endTime.getSeconds() + "\n"; | |
832 | returnData += " nanoSeconds : " + endTime.getNanoSeconds() + "\n"; | |
833 | returnData += "tracefilesMap : " + tracefilesMap.keySet() + "\n"; // Hack to avoid ending up with tracefilesMap.toString() | |
834 | ||
835 | return returnData; | |
836 | } | |
837 | ||
c357e4b6 WB |
838 | |
839 | // **************************** | |
840 | // **** ABSTRACT FUNCTIONS **** | |
841 | // You MUST override those in your version specific implementation | |
842 | ||
843 | /** | |
844 | * Function place holder to load the correct C library.<p> | |
845 | * <br> | |
846 | * Can be as simple as calling ltt_initializeHandle(LIBRARY_NAME) with the correct .so instead of LIBRARY_NAME.<br> | |
847 | * You may also want to perform some check or some additionnal validations.<br> | |
848 | * <br> | |
849 | * <b>!! Override this with you version specific implementation.</b><br> | |
850 | * | |
c85e8cb2 | 851 | * @return integer that is the library id, or -1 if the load was unsuccessful |
c357e4b6 | 852 | */ |
c85e8cb2 | 853 | public abstract int initializeLibrary(); |
0152140d | 854 | |
c357e4b6 WB |
855 | |
856 | /** | |
857 | * Function place holder to allocate a new JniTracefile.<p> | |
858 | * | |
859 | * JniTracefile constructor is non overridable so we need another overridable function to return the correct version of JniTracefile.<br> | |
860 | * Effect of this function should be the same (allocate a fresh new JniTracefile)<br> | |
861 | * <br> | |
862 | * <b>!! Override this with you version specific implementation.</b><br> | |
863 | * | |
864 | * @param newPtr The pointer of an already opened LttTracefile C Structure | |
865 | * @param newParentTrace The JniTrace parent of this tracefile. | |
866 | * | |
867 | * @return The newly allocated JniTracefile of the correct version | |
868 | * | |
869 | * @throws JniException The construction (allocation) failed. | |
870 | * | |
871 | * @see org.eclipse.linuxtools.lttng.jni.JniTracefile | |
c85e8cb2 | 872 | * @see org.eclipse.linuxtools.lttng.jni.common.Jni_C_Pointer_And_Library_Id |
c357e4b6 WB |
873 | * @see org.eclipse.linuxtools.lttng.jni.JniTrace |
874 | */ | |
c85e8cb2 | 875 | public abstract JniTracefile allocateNewJniTracefile(Jni_C_Pointer_And_Library_Id newPtr, JniTrace newParentTrace) throws JniException; |
0152140d | 876 | |
c357e4b6 | 877 | } |