Commit | Line | Data |
---|---|---|
28b94d61 | 1 | package org.eclipse.linuxtools.lttng.jni; |
88144d4a ASL |
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 | ||
15 | import java.util.HashMap; | |
16 | ||
17 | /** | |
07d9e2ee FC |
18 | * <b><u>JniEvent</u></b> <p> |
19 | * | |
20 | * A JniEvent has the actual content that got traced by Lttng.<br> | |
21 | * Provides access to the LttEvent C structure in java. <p> | |
22 | * | |
88144d4a ASL |
23 | * Most important fields in the JniEvent are : |
24 | * <ul> | |
07d9e2ee | 25 | * <li>an event time, which is a digested timestamp. |
88144d4a ASL |
26 | * </ul> |
27 | * Note that the JniEvent content is not directly accessibe and should be obtained | |
07d9e2ee | 28 | * using the parseAllFields() or parseFieldBy...() methods. |
88144d4a | 29 | */ |
07d9e2ee | 30 | public final class JniEvent extends Jni_C_Common implements Comparable<JniEvent> { |
88144d4a ASL |
31 | // Variables to detect if the event have been filled at least once |
32 | // this make possible the detection of "uninitialized" struct in Ltt | |
33 | // Can be "EOK", "ERANGE" or "EPERM" (defined in Jaf_C_Common) | |
34 | private int eventState = EPERM; // Start with EPERM to ensure sanity | |
35 | ||
36 | // Internal C pointer of the JniEvent used in LTT | |
07d9e2ee | 37 | private Jni_C_Pointer thisEventPtr = new Jni_C_Pointer(); |
88144d4a ASL |
38 | |
39 | // Reference to the parent tracefile | |
40 | private JniTracefile parentTracefile = null; | |
41 | ||
42 | // This map hold marker relative to the parent tracefile of this event | |
43 | // They are "our" marker in this event | |
07d9e2ee | 44 | private HashMap<Integer, JniMarker> markersMap = null; |
88144d4a ASL |
45 | |
46 | // Data we should populate from ltt | |
47 | // Note that all type have been scaled up as there is no "unsigned" in java | |
48 | // This might be a problem about "unsigned long" as there is no equivalent | |
49 | // in java | |
28b94d61 | 50 | private Jni_C_Pointer tracefilePtr = new Jni_C_Pointer(); |
88144d4a ASL |
51 | private JniTime eventTime = null; |
52 | ||
53 | // These methods need a tracefile pointer, instead of a event pointer | |
54 | private native int ltt_readNextEvent(long tracefilePtr); | |
55 | private native int ltt_seekEvent(long tracefilePtr, JniTime givenTime); | |
56 | private native int ltt_positionToFirstEvent(long tracefilePtr); | |
57 | ||
58 | // Native access functions | |
59 | private native long ltt_getTracefilePtr(long eventPtr); | |
60 | @SuppressWarnings("unused") | |
61 | private native long ltt_getBlock(long eventPtr); | |
62 | @SuppressWarnings("unused") | |
63 | private native long ltt_getOffset(long eventPtr); | |
64 | @SuppressWarnings("unused") | |
65 | private native long ltt_getCurrentTimestampCounter(long eventPtr); | |
66 | @SuppressWarnings("unused") | |
67 | private native long ltt_getTimestamp(long eventPtr); | |
68 | private native int ltt_getEventMarkerId(long eventPtr); | |
28b94d61 FC |
69 | private native long ltt_getNanosencondsTime(long eventPtr); |
70 | @SuppressWarnings("unused") | |
88144d4a ASL |
71 | private native void ltt_feedEventTime(long eventPtr, JniTime eventTime); |
72 | private native long ltt_getEventDataSize(long eventPtr); | |
73 | @SuppressWarnings("unused") | |
74 | private native long ltt_getEventSize(long eventPtr); | |
75 | @SuppressWarnings("unused") | |
76 | private native int ltt_getCount(long eventPtr); | |
77 | @SuppressWarnings("unused") | |
78 | private native long ltt_getOverflowNanoSeconds(long eventPtr); | |
79 | ||
80 | // This method an event pointer | |
81 | private native void ltt_getDataContent(long eventPtr, long dataSize, byte[] returnedContent); | |
82 | ||
83 | // Debug native function, ask LTT to print event structure | |
84 | private native void ltt_printEvent(long eventPtr); | |
85 | ||
86 | static { | |
87 | System.loadLibrary("lttvtraceread"); | |
88 | } | |
89 | ||
90 | ||
91 | /** | |
92 | * Default constructor is forbidden | |
93 | */ | |
94 | @SuppressWarnings("unused") | |
95 | private JniEvent() { | |
96 | }; | |
97 | ||
98 | /** | |
07d9e2ee | 99 | * Copy constructor.<p> |
88144d4a | 100 | * |
07d9e2ee | 101 | * @param oldEvent Reference to the JniEvent you want to copy. |
88144d4a ASL |
102 | */ |
103 | public JniEvent(JniEvent oldEvent) { | |
104 | thisEventPtr = oldEvent.thisEventPtr; | |
105 | markersMap = oldEvent.markersMap; | |
106 | parentTracefile = oldEvent.parentTracefile; | |
107 | eventState = oldEvent.eventState; | |
108 | ||
109 | tracefilePtr = oldEvent.tracefilePtr; | |
110 | eventTime = oldEvent.eventTime; | |
111 | } | |
112 | ||
113 | /** | |
07d9e2ee FC |
114 | * Constructor with parameters<p> |
115 | * | |
116 | * This constructor could throw. It will happen if an event can not be populated on <u>first read</u>.<br> | |
88144d4a ASL |
117 | * In that case, the parent tracefile is probably useless and should be deleted. |
118 | * | |
119 | * @param newEventPtr C pointer (converted in long) of the LttEvent C structure. | |
120 | * @param newMarkersMap Reference an already populated HashMap of JniMarker objects | |
121 | * @param newParentTracefile Reference to the parent JniTracefile of this JniEvent | |
122 | * | |
07d9e2ee FC |
123 | * @exception JniException |
124 | * | |
28b94d61 FC |
125 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer |
126 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker | |
127 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile | |
88144d4a | 128 | */ |
07d9e2ee | 129 | public JniEvent(Jni_C_Pointer newEventPtr, HashMap<Integer, JniMarker> newMarkersMap, JniTracefile newParentTracefile) throws JniException { |
88144d4a ASL |
130 | |
131 | // Basic test to make sure we didn't get null/empty value | |
132 | if ((newEventPtr.getPointer() == NULL) | |
133 | || (newMarkersMap == null) | |
134 | || (newMarkersMap.size() == 0) | |
135 | || (newParentTracefile == null)) { | |
136 | throw new JniEventException("Null or empty value passed to constructor, object is invalid! (JniEvent)"); | |
137 | } | |
d2fe33b6 | 138 | |
88144d4a ASL |
139 | thisEventPtr = newEventPtr; |
140 | tracefilePtr = newParentTracefile.getTracefilePtr(); | |
141 | markersMap = newMarkersMap; | |
142 | parentTracefile = newParentTracefile; | |
143 | ||
144 | eventTime = new JniTime(); | |
d2fe33b6 | 145 | |
88144d4a | 146 | // Try to move to the first event |
07d9e2ee | 147 | // If the event is Out of Range (ERANGE) at the first read, |
28b94d61 | 148 | // this event type will never be usable. |
07d9e2ee | 149 | // In that case, throw JniNoSuchEventException to warn the tracefile. |
88144d4a | 150 | eventState = positionToFirstEvent(); |
07d9e2ee | 151 | if (eventState != EOK) { |
88144d4a ASL |
152 | throw new JniNoSuchEventException("Object not populated, unusable. There is probably no event of that type in the trace. (JniEvent)"); |
153 | } | |
154 | else { | |
155 | populateEventInformation(); | |
156 | } | |
157 | } | |
158 | ||
159 | /** | |
07d9e2ee FC |
160 | * Move to the next event and populate the java object with LttEvent structure.<p> |
161 | * | |
162 | * If the move fails, the event will not get populated and the last event data will still be available. | |
163 | * | |
164 | * @return LTT read status, as defined in Jni_C_Common. | |
88144d4a | 165 | * |
28b94d61 | 166 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common |
88144d4a ASL |
167 | */ |
168 | public int readNextEvent() { | |
169 | // Ask Ltt to read the next event for this particular tracefile | |
28b94d61 | 170 | eventState = ltt_readNextEvent( tracefilePtr.getPointer() ); |
88144d4a ASL |
171 | // If the event state is sane populate it |
172 | if (eventState == EOK) { | |
173 | populateEventInformation(); | |
174 | } | |
28b94d61 | 175 | |
88144d4a ASL |
176 | return eventState; |
177 | } | |
178 | ||
179 | /** | |
07d9e2ee FC |
180 | * Seek to a certain time.<p> |
181 | * | |
182 | * Seek to a certain time and read event at this exact time or the next one if there is no event there.<p> | |
183 | * | |
184 | * Note that this function can seek in an invalid position if the timestamp is after the last event.<br> | |
185 | * In that case, a seek back would be required to get back to a consistent state.<p> | |
186 | * | |
187 | * If the seek fails, the event will not get populated and the last event data will still be available.<p> | |
188 | * | |
189 | * @return LTT read status, as defined in Jni_C_Common | |
88144d4a | 190 | * |
28b94d61 | 191 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common |
88144d4a ASL |
192 | */ |
193 | public int seekToTime(JniTime seekTime) { | |
194 | // Ask Ltt to read the next event for this particular tracefile | |
195 | eventState = ltt_seekEvent(tracefilePtr.getPointer(), seekTime); | |
196 | ||
197 | // If the event state is sane populate it | |
198 | if (eventState == EOK) { | |
199 | populateEventInformation(); | |
200 | } | |
201 | ||
202 | return eventState; | |
203 | } | |
204 | ||
205 | /** | |
07d9e2ee FC |
206 | * Try to seek to a certain time and seek back if it failed.<p> |
207 | * | |
208 | * Seek to a certain time and read event at this exact time or the next one if there is no event there.<p> | |
209 | * | |
210 | * If the seek fails, we will seek back to the previous position, so the event will stay in a consistent state.<p> | |
211 | * | |
212 | * @return LTT read status, as defined in Jni_C_Common | |
88144d4a | 213 | * |
28b94d61 | 214 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common |
88144d4a ASL |
215 | */ |
216 | public int seekOrFallBack(JniTime seekTime) { | |
217 | // Save the old time | |
28b94d61 | 218 | JniTime oldTime = new JniTime(eventTime); |
88144d4a ASL |
219 | |
220 | // Call seek to move ahead | |
07d9e2ee FC |
221 | // Save the state for the return (eventState will be modified if we seek back) |
222 | int returnState = seekToTime(seekTime); | |
88144d4a ASL |
223 | |
224 | // If the event state is sane populate it | |
07d9e2ee | 225 | if (returnState == EOK) { |
88144d4a ASL |
226 | populateEventInformation(); |
227 | } | |
07d9e2ee | 228 | else { |
88144d4a ASL |
229 | seekToTime(oldTime); |
230 | } | |
231 | ||
232 | return returnState; | |
233 | } | |
234 | ||
235 | /** | |
07d9e2ee FC |
236 | * Position on the first event in the tracefile.<p> |
237 | * | |
238 | * The function return the read status after the first event.<p> | |
239 | * | |
240 | * A status different of EOK probably means there is no event associated to this tracefile. | |
241 | * | |
242 | * @return LTT read status, as defined in Jni_C_Common | |
88144d4a | 243 | * |
28b94d61 | 244 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Common |
88144d4a ASL |
245 | */ |
246 | public int positionToFirstEvent() { | |
247 | eventState = ltt_positionToFirstEvent(tracefilePtr.getPointer()); | |
248 | ||
249 | return eventState; | |
250 | } | |
251 | ||
252 | /** | |
07d9e2ee | 253 | * Obtain a marker associated with this tracefile's event. |
88144d4a | 254 | * |
07d9e2ee FC |
255 | * @return Reference to the marker for this tracefile's event or null if none. |
256 | * | |
28b94d61 | 257 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker |
88144d4a ASL |
258 | */ |
259 | public JniMarker requestEventMarker() { | |
28b94d61 | 260 | return markersMap.get(getEventMarkerId()); |
88144d4a ASL |
261 | } |
262 | ||
263 | /** | |
07d9e2ee | 264 | * Obtain the raw data of a LttEvent object.<p> |
88144d4a | 265 | * |
07d9e2ee FC |
266 | * The data will be in raw C bytes, not java bytes.<br> |
267 | * Note : This function is mostly untested and provided "as is". | |
268 | * | |
269 | * @return Bytes array of raw data (contain raw C bytes). | |
88144d4a ASL |
270 | */ |
271 | public byte[] requestEventContent() { | |
28b94d61 | 272 | byte dataContent[] = new byte[(int) getEventDataSize()]; |
146a887c | 273 | |
28b94d61 | 274 | ltt_getDataContent(thisEventPtr.getPointer(), getEventDataSize(), dataContent); |
88144d4a ASL |
275 | |
276 | return dataContent; | |
277 | } | |
07d9e2ee | 278 | |
88144d4a | 279 | /** |
07d9e2ee FC |
280 | * Obtain an event source.<p> |
281 | * | |
88144d4a ASL |
282 | * This is not implemented yet and will always return "Kernel core" for now. |
283 | * | |
284 | * @return Reference to the JniMarker object for this event or null if none. | |
07d9e2ee | 285 | * |
28b94d61 | 286 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniMarker |
88144d4a ASL |
287 | */ |
288 | public String requestEventSource() { | |
07d9e2ee FC |
289 | // *** TODO *** |
290 | // No "Source" of event exists in Ltt so far | |
291 | // It would be a good addition to have a way to detect where an event come | |
292 | // from, like "kernel" or "userspace" | |
293 | // | |
88144d4a ASL |
294 | return "Kernel Core"; |
295 | } | |
296 | ||
297 | /** | |
07d9e2ee FC |
298 | * Parse a particular field in the event payload, identified by its id (position).<p> |
299 | * | |
300 | * Note : Position are relative to an event marker (i.e. requestEventMarker().getMarkerFieldsArrayList() ) | |
301 | * | |
302 | * @param fieldId Position of the field to parse. | |
88144d4a ASL |
303 | * |
304 | * @return Object that contain the parsed payload | |
28b94d61 FC |
305 | * |
306 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser | |
88144d4a ASL |
307 | */ |
308 | public Object parseFieldById(int fieldId) { | |
309 | return JniParser.parseField(this, fieldId); | |
310 | } | |
311 | ||
312 | /** | |
07d9e2ee FC |
313 | * Parse a particular field in the event payload, identified by its name.<p> |
314 | * | |
315 | * Note : Name are relative to an event marker (i.e. requestEventMarker().getMarkerFieldsHashMap() ) | |
316 | * | |
317 | * @param fieldName Position of the field to parse. | |
88144d4a ASL |
318 | * |
319 | * @return Object that contain the parsed payload | |
28b94d61 FC |
320 | * |
321 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser | |
88144d4a ASL |
322 | */ |
323 | public Object parseFieldByName(String fieldName) { | |
324 | return JniParser.parseField(this, fieldName); | |
325 | } | |
326 | ||
327 | /** | |
07d9e2ee | 328 | * Method to parse all the event payload.<p> |
88144d4a | 329 | * |
28b94d61 FC |
330 | * @return HashMap<String, Object> which is the parsedContent objects and their name as key. |
331 | * | |
332 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniParser | |
88144d4a ASL |
333 | */ |
334 | public HashMap<String, Object> parseAllFields() { | |
335 | return JniParser.parseAllFields(this); | |
336 | } | |
337 | ||
338 | /* | |
339 | * This function populates the event data with data from LTT | |
340 | * | |
28b94d61 FC |
341 | * NOTE : To get better performance, we copy very few data into memory here |
342 | * | |
88144d4a ASL |
343 | */ |
344 | private void populateEventInformation() { | |
28b94d61 FC |
345 | // We need to save the time, as it is not a primitive (can't be dynamically called in getter) |
346 | eventTime.setTime(ltt_getNanosencondsTime(thisEventPtr.getPointer() )); | |
88144d4a ASL |
347 | } |
348 | ||
349 | public JniTime getEventTime() { | |
350 | return eventTime; | |
351 | } | |
28b94d61 FC |
352 | |
353 | // *** To get better performance, all getter belows call LTT directly **** | |
354 | // That way, we can avoid copying data into memory | |
355 | public int getEventMarkerId() { | |
356 | return ltt_getEventMarkerId(thisEventPtr.getPointer()); | |
357 | } | |
88144d4a ASL |
358 | |
359 | public long getEventDataSize() { | |
28b94d61 | 360 | return ltt_getEventDataSize(thisEventPtr.getPointer()); |
88144d4a ASL |
361 | } |
362 | ||
363 | public HashMap<Integer, JniMarker> getMarkersMap() { | |
364 | return markersMap; | |
365 | } | |
366 | ||
367 | /** | |
07d9e2ee | 368 | * Pointer to the parent LTTTracefile C structure.<br> |
88144d4a | 369 | * <br> |
07d9e2ee | 370 | * The pointer should only be used <u>INTERNALY</u>, do not use unless you |
88144d4a ASL |
371 | * know what you are doing. |
372 | * | |
07d9e2ee FC |
373 | * @return The actual (long converted) pointer or NULL. |
374 | * | |
28b94d61 | 375 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer |
88144d4a | 376 | */ |
07d9e2ee | 377 | public Jni_C_Pointer getTracefilePtr() { |
28b94d61 | 378 | return new Jni_C_Pointer( ltt_getTracefilePtr(thisEventPtr.getPointer()) ); |
88144d4a ASL |
379 | } |
380 | ||
381 | /** | |
07d9e2ee | 382 | * Pointer to the LttEvent C structure.<br> |
88144d4a | 383 | * <br> |
07d9e2ee | 384 | * The pointer should only be used <u>INTERNALY</u>, do not use unless you |
88144d4a ASL |
385 | * know what you are doing. |
386 | * | |
07d9e2ee FC |
387 | * @return The actual (long converted) pointer or NULL. |
388 | * | |
28b94d61 | 389 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.Jni_C_Pointer |
88144d4a | 390 | */ |
07d9e2ee | 391 | public Jni_C_Pointer getEventPtr() { |
88144d4a ASL |
392 | return thisEventPtr; |
393 | } | |
394 | ||
395 | public int getEventState() { | |
396 | return eventState; | |
397 | } | |
398 | ||
399 | /** | |
400 | * Getter to the parent tracefile for this event. | |
401 | * | |
07d9e2ee | 402 | * @return The parent tracefile |
88144d4a | 403 | * |
28b94d61 | 404 | * @see org.eclipse.linuxtools.lttng.jni.eclipse.linuxtools.lttng.jni.JniTracefile |
88144d4a ASL |
405 | */ |
406 | public JniTracefile getParentTracefile() { | |
407 | return parentTracefile; | |
408 | } | |
07d9e2ee FC |
409 | |
410 | /** | |
411 | * Compare fonction for JNIEvent.<p> | |
412 | * <p> | |
413 | * This will compare the current JNIEvent with a passed one by timestamp AND tracefile ("type").<br> | |
414 | * If both are equal but type differs, current event is considered to be older (-1 returned). | |
415 | * | |
416 | * @return -1 if given event happens before, 0 if equal, 1 if passed event happens after. | |
417 | */ | |
07d9e2ee | 418 | public int compareTo(JniEvent rightEvent ){ |
28b94d61 FC |
419 | |
420 | // Note : this = left hand operand | |
421 | ||
07d9e2ee FC |
422 | // By default, we consider the current event to be older. |
423 | int eventComparaison = -1; | |
424 | ||
425 | // Test against null before performing anything | |
426 | if ( rightEvent != null ) { | |
427 | // Compare the timestamp first | |
28b94d61 | 428 | eventComparaison = this.getEventTime().compareTo( rightEvent.getEventTime() ); |
07d9e2ee FC |
429 | |
430 | // If timestamp is equal, compare the parent tracefile ("event type") | |
28b94d61 | 431 | if ( (eventComparaison == 0) && ( !this.parentTracefile.equals(rightEvent.parentTracefile)) ) { |
07d9e2ee FC |
432 | eventComparaison = 1; |
433 | } | |
434 | } | |
435 | return eventComparaison; | |
436 | } | |
437 | ||
438 | /** | |
439 | * Print information for this event. | |
440 | * <u>Intended to debug</u><br> | |
441 | * | |
442 | * This function will call Ltt to print, so information printed will be | |
443 | * the one from the C structure, not the one populated in java.<p> | |
444 | * | |
445 | * This function will not throw but will complain loudly if pointer is NULL. | |
446 | */ | |
447 | public void printEventInformation() { | |
146a887c | 448 | |
07d9e2ee FC |
449 | // If null pointer, print a warning! |
450 | if (thisEventPtr.getPointer() == NULL) { | |
451 | printlnC("Pointer is NULL, cannot print. (printEventInformation)"); | |
452 | } | |
453 | else { | |
454 | ltt_printEvent(thisEventPtr.getPointer()); | |
455 | } | |
456 | } | |
457 | ||
88144d4a | 458 | /** |
07d9e2ee FC |
459 | * toString() method. |
460 | * <u>Intended to debug.</u><p> | |
88144d4a | 461 | * |
07d9e2ee | 462 | * @return Attributes of the object concatenated in String |
88144d4a | 463 | */ |
6d848cce FC |
464 | @Override |
465 | public String toString() { | |
146a887c FC |
466 | String returnData = ""; |
467 | ||
468 | returnData += "tracefilePtr : " + tracefilePtr + "\n"; | |
28b94d61 | 469 | returnData += "eventMarkerId : " + getEventMarkerId() + "\n"; |
146a887c FC |
470 | returnData += "eventTime : " + eventTime.getReferenceToString() + "\n"; |
471 | returnData += " seconds : " + eventTime.getSeconds() + "\n"; | |
472 | returnData += " nanoSeconds : " + eventTime.getNanoSeconds() + "\n"; | |
28b94d61 | 473 | returnData += "eventDataSize : " + getEventDataSize() + "\n"; |
146a887c FC |
474 | returnData += "markersMap : " + markersMap.keySet() + "\n"; // Hack to avoid ending up with markersMap.toString() |
475 | ||
476 | return returnData; | |
88144d4a | 477 | } |
88144d4a | 478 | } |