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