1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
10 * William Bourque (wbourque@gmail.com) - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.lttng
.trace
;
15 import java
.io
.BufferedReader
;
16 import java
.io
.FileReader
;
17 import java
.io
.IOException
;
18 import java
.util
.HashMap
;
20 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
21 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventContent
;
22 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventField
;
23 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventReference
;
24 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventSource
;
25 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventType
;
26 import org
.eclipse
.linuxtools
.lttng
.event
.LttngTimestamp
;
27 import org
.eclipse
.linuxtools
.lttng
.jni
.JniEvent
;
28 import org
.eclipse
.linuxtools
.tmf
.event
.TmfNoSuchFieldException
;
29 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
30 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfLocation
;
31 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfTrace
;
32 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfCheckpoint
;
33 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfContext
;
34 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfLocation
;
35 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfTrace
;
37 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> implements ITmfTrace
{
38 private LttngTimestamp eventTimestamp
= null;
39 private LttngEventSource eventSource
= null;
40 private LttngEventType eventType
= null;
41 private TextLttngEventContent eventContent
= null;
42 private LttngEventReference eventReference
= null;
44 private TextLttngEvent currentLttngEvent
= null;
46 private HashMap
<String
, LttngEventType
> traceTypes
= null;
48 private String tracepath
= "";
49 private FileReader fr
= null;
50 private BufferedReader br
= null;
51 private Long nbCharRead
= 0L;
53 private int cpuNumber
= -1;
55 private boolean showDebug
= false;
57 public LTTngTextTrace(String path
) throws Exception
{
61 public LTTngTextTrace(String path
, boolean skipIndexing
) throws Exception
{
62 super(LttngEvent
.class, path
, 1);
65 traceTypes
= new HashMap
<String
, LttngEventType
>();
67 eventTimestamp
= new LttngTimestamp();
68 eventSource
= new LttngEventSource();
69 eventType
= new LttngEventType();
70 eventContent
= new TextLttngEventContent(currentLttngEvent
);
71 eventReference
= new LttngEventReference(this.getName());
73 currentLttngEvent
= new TextLttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
);
74 eventContent
.setEvent(currentLttngEvent
);
76 if ( positionToFirstEvent() == false ) {
77 throw new IOException("Fail to position to the beginning of the trace");
80 fIndexPageSize
= 1000;
82 // Skip indexing if asked
83 if ( skipIndexing
== true ) {
84 fCheckpoints
.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation
<Long
>(0L)));
90 Long endTime
= currentLttngEvent
.getTimestamp().getValue();
91 positionToFirstEvent();
93 getNextEvent(new TmfContext(null, 0));
94 Long starTime
= currentLttngEvent
.getTimestamp().getValue();
95 positionToFirstEvent();
97 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
98 new LttngTimestamp(endTime
)
104 public LTTngTextTrace(LTTngTextTrace oldTrace
) throws Exception
{
105 this(oldTrace
.getPath(), true);
109 fCheckpoints
= oldTrace
.fCheckpoints
;
112 public LTTngTextTrace
createTraceCopy() {
114 LTTngTextTrace returnedTrace
= null;
117 returnedTrace
= new LTTngTextTrace(this);
119 catch (Exception e
) {
120 System
.out
.println("ERROR : Could not create LTTngTextTrace copy (createTraceCopy).\nError is : " + e
.getStackTrace());
123 return returnedTrace
;
126 private boolean positionToFirstEvent() {
128 boolean isSuccessful
= true;
136 fr
= new FileReader(tracepath
);
137 br
= new BufferedReader(fr
);
139 // Skip the 2 lines header
143 // Make sure the event time is consistent
144 eventTimestamp
.setValue(0L);
146 catch (Exception e
) {
147 isSuccessful
= false;
153 private void skipToPosition(TmfLocation
<Long
> skip
) {
155 long skipPosition
= skip
.getLocation();
156 if ( skipPosition
< 0 ) {
160 if ( showDebug
== true ) {
161 System
.out
.println("skipToPosition(Long skipPosition)");
162 System
.out
.println("\tSkipping to : " + skipPosition
);
163 System
.out
.println();
165 positionToFirstEvent();
166 long nbSkipped
= br
.skip(skipPosition
);
167 if ( nbSkipped
!= skipPosition
) {
168 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)");
171 nbCharRead
= skipPosition
;
173 catch (Exception e
) {
179 @SuppressWarnings("unchecked")
180 public TmfContext
seekLocation(ITmfLocation
<?
> location
) {
181 if (location
== null) {
182 location
= new TmfLocation
<Long
>(0L);
185 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
)) {
186 skipToPosition((TmfLocation
<Long
>) location
);
189 TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
191 return tmpTraceContext
;
194 private LttngEvent
parseMyNextEvent(TmfContext context
) {
196 // All parsing variables declared here so to be able to print them into the catch if needed
197 String tmpContent
= null;
199 int tmpPrevIndex
= 0;
201 String tracefile
= "";
206 long tmpNanosecond
= 0;
208 String parsedPayload
= "";
209 String markerName
= "";
212 HashMap
<String
, LttngEventField
> fieldsMap
= null;
214 LttngEvent returnedEvent
= null;
217 tmpContent
= br
.readLine();
219 if (tmpContent
!= null) {
221 // -1 is the skip the end of line (\n)
222 nbCharRead
+= (tmpContent
.length()+1);
224 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getRawContent() != null) ) {
225 currentLttngEvent
.getContent().emptyContent();
228 // EventSource is always the same for now :
229 eventSource
.setSourceId("Kernel Core");
232 // Tracefile and marker are first in the file
234 // kernel.syscall_entry:
235 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
238 // Evil exit case here : the two last line of the text dump does not contain "."
239 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
240 // Conclusion : this is ugly but fast.
241 if ( tmpCurIndex
< 0 ) {
242 if ( showDebug
== true ) {
243 System
.out
.println("END OF FILE.");
244 System
.out
.println();
249 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
250 /*System.out.println(tracefile);*/
252 tmpPrevIndex
= tmpCurIndex
;
253 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
);
254 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
255 /*System.out.println(marker);*/
257 // Timestamp is next but is presented in second.milisecond format, we have to split them
260 tmpPrevIndex
= tmpCurIndex
+1;
261 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
262 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
263 /*System.out.println(tmpSecond);*/
265 tmpPrevIndex
= tmpCurIndex
+1;
266 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
);
267 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
268 /*System.out.println(tmpNanosecond);*/
270 // We have enough information here to set the timestamp
271 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
272 /*System.out.println(eventTimestamp.toString());*/
274 // Next field is the reference
275 // A long string enclosed by parenthesis and ending with a comma
276 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
277 tmpPrevIndex
= tmpCurIndex
+1;
278 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
);
279 tmpPrevIndex
= tmpCurIndex
+1;
280 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
);
281 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
282 /*System.out.println(fullTracePath);*/
284 eventReference
.setValue(fullTracePath
);
285 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim();
286 /*System.out.println(traceName);*/
287 eventReference
.setTracepath(traceName
);
290 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
291 // They should be like the following :
292 // 4175, 4175, hal-acl-tool, , 4168,
295 tmpPrevIndex
= tmpCurIndex
+1;
296 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
298 tmpPrevIndex
= tmpCurIndex
+1;
299 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
301 tmpPrevIndex
= tmpCurIndex
+1;
302 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
304 tmpPrevIndex
= tmpCurIndex
+1;
305 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
307 tmpPrevIndex
= tmpCurIndex
+1;
308 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
310 tmpPrevIndex
= tmpCurIndex
+1;
311 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
313 // The next field is the CPU, in hexadecimal format
316 tmpPrevIndex
= tmpCurIndex
+1;
317 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
);
318 tmpPrevIndex
= tmpCurIndex
+2;
320 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
321 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
323 // Set the cpu number of trace if we found a "new" cpu
324 if ( cpuNumber
< (tmpCpu
+ 1) ) {
325 cpuNumber
= (int)(tmpCpu
+1);
327 /*System.out.println(tmpCpu);*/
330 // The last field is the parsed content
331 // It is enclosed by { }
333 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
335 // NOTE : it seems some state system events do not respect this format as they have no payload.
336 // We will create empty payload then.
337 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
);
338 if ( tmpIndex
!= -1 ) {
339 tmpPrevIndex
= tmpCurIndex
+1;
340 tmpCurIndex
= tmpIndex
;
341 tmpPrevIndex
= tmpCurIndex
+1;
342 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
);
343 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
345 // Now add each LttngField
346 boolean isDone
= false;
347 int tmpIndexBegin
= 0;
348 int tmpIndexEqual
= 0;
351 fieldsMap
= new HashMap
<String
, LttngEventField
>();
353 while ( isDone
== false ) {
354 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
);
355 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
);
356 if ( tmpIndexEnd
== -1 ) {
357 tmpIndexEnd
= parsedPayload
.length();
361 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
362 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim();
364 // Try to cast the payload into the correct type
366 payload
= Long
.parseLong((String
)payload
);
368 catch (NumberFormatException e
) { }
370 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
371 fieldsMap
.put(markerName
, tmpField
);
373 tmpIndexBegin
= tmpIndexEnd
+1;
377 fieldsMap
= new HashMap
<String
, LttngEventField
>();
382 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
383 fieldsMap
.put(markerName
, tmpField
);
386 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
388 // We now have what we need for the type
389 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
;
390 if ( traceTypes
.get(tmpTypeKey
) == null ) {
391 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
394 currentLttngEvent
.setContent(eventContent
);
395 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
397 returnedEvent
= currentLttngEvent
;
399 else if ( showDebug
== true ) {
400 System
.out
.println("NULL READING");
401 System
.out
.println();
402 returnedEvent
= null;
405 catch (Exception e
) {
406 System
.out
.println("Pos is :" + nbCharRead
);
407 if ( tmpContent
!= null ) {
408 System
.out
.println("Erroneous content is :" + tmpContent
);
413 returnedEvent
= null;
416 return returnedEvent
;
420 public ITmfLocation
<?
> getCurrentLocation() {
421 return new TmfLocation
<Long
>(nbCharRead
);
425 public LttngEvent
parseEvent(TmfContext context
) {
426 context
= seekLocation(context
.getLocation());
427 return parseMyNextEvent(context
);
431 public int getCpuNumber() {
437 // Redefine event to override method we know won't work with a Text tracefile
438 class TextLttngEvent
extends LttngEvent
{
440 public TextLttngEvent( TmfTrace
<LttngEvent
> parent
,
441 LttngTimestamp timestamp
,
442 LttngEventSource source
,
444 LttngEventContent content
,
445 LttngEventReference reference
)
447 super(parent
, timestamp
, source
, type
, content
, reference
, null);
450 public TextLttngEvent(TextLttngEvent oldEvent
) {
452 oldEvent
.getParentTrace(),
453 (LttngTimestamp
)oldEvent
.getTimestamp(),
454 (LttngEventSource
)oldEvent
.getSource(),
455 (LttngEventType
)oldEvent
.getType(),
456 (LttngEventContent
)oldEvent
.getContent(),
457 (LttngEventReference
)oldEvent
.getReference()
462 public JniEvent
convertEventTmfToJni() {
463 System
.out
.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format.");
468 public void updateJniEventReference(JniEvent newJniEventReference
) {
469 System
.out
.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null.");
474 class TextLttngEventContent
extends LttngEventContent
{
476 public TextLttngEventContent() {
480 public TextLttngEventContent(TextLttngEvent thisParent
) {
481 super(thisParent
, null);
484 public TextLttngEventContent(TextLttngEvent thisParent
, HashMap
<String
, LttngEventField
> thisContent
) {
485 super(thisParent
, thisContent
);
488 public TextLttngEventContent(TextLttngEventContent oldContent
) {
489 this( (TextLttngEvent
)oldContent
.fParentEvent
, oldContent
.getRawContent());
493 public LttngEventField
[] getFields() {
494 return getRawContent().values().toArray(new LttngEventField
[getRawContent().size()]);
498 public LttngEventField
getField(String name
) {
499 LttngEventField returnedField
= getRawContent().get(name
);
501 return returnedField
;
505 public LttngEventField
getField(int position
) {
506 LttngEventField returnedField
= null;
509 label
= fParentEvent
.getType().getLabel(position
);
510 returnedField
= this.getField(label
);
512 catch (TmfNoSuchFieldException e
) {
513 System
.out
.println("Invalid field position requested : " + position
+ ", ignoring (getField).");
516 return returnedField
;