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(path
, 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
;
113 public LTTngTextTrace
createTraceCopy() {
115 LTTngTextTrace returnedTrace
= null;
118 returnedTrace
= new LTTngTextTrace(this);
120 catch (Exception e
) {
121 System
.out
.println("ERROR : Could not create LTTngTextTrace copy (createTraceCopy).\nError is : " + e
.getStackTrace());
124 return returnedTrace
;
127 private boolean positionToFirstEvent() {
129 boolean isSuccessful
= true;
137 fr
= new FileReader(tracepath
);
138 br
= new BufferedReader(fr
);
140 // Skip the 2 lines header
144 // Make sure the event time is consistent
145 eventTimestamp
.setValue(0L);
147 catch (IOException e
) {
148 isSuccessful
= false;
154 private void skipToPosition(TmfLocation
<Long
> skip
) {
156 long skipPosition
= skip
.getLocation();
157 if ( skipPosition
< 0 ) {
161 if ( showDebug
== true ) {
162 System
.out
.println("skipToPosition(Long skipPosition)");
163 System
.out
.println("\tSkipping to : " + skipPosition
);
164 System
.out
.println();
166 positionToFirstEvent();
167 long nbSkipped
= br
.skip(skipPosition
);
168 if ( nbSkipped
!= skipPosition
) {
169 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)");
172 nbCharRead
= skipPosition
;
174 catch (Exception e
) {
180 @SuppressWarnings("unchecked")
181 public TmfContext
seekLocation(ITmfLocation
<?
> location
) {
182 if (location
== null) {
183 location
= new TmfLocation
<Long
>(0L);
186 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
)) {
187 skipToPosition((TmfLocation
<Long
>) location
);
190 TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
192 return tmpTraceContext
;
195 private LttngEvent
parseMyNextEvent(TmfContext context
) {
197 // All parsing variables declared here so to be able to print them into the catch if needed
198 String tmpContent
= null;
200 int tmpPrevIndex
= 0;
202 String tracefile
= "";
207 long tmpNanosecond
= 0;
209 String parsedPayload
= "";
210 String markerName
= "";
213 HashMap
<String
, LttngEventField
> fieldsMap
= null;
215 LttngEvent returnedEvent
= null;
218 tmpContent
= br
.readLine();
220 if (tmpContent
!= null) {
222 // -1 is the skip the end of line (\n)
223 nbCharRead
+= (tmpContent
.length()+1);
225 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getRawContent() != null) ) {
226 currentLttngEvent
.getContent().emptyContent();
229 // EventSource is always the same for now :
230 eventSource
.setSourceId("Kernel Core");
233 // Tracefile and marker are first in the file
235 // kernel.syscall_entry:
236 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
239 // Evil exit case here : the two last line of the text dump does not contain "."
240 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
241 // Conclusion : this is ugly but fast.
242 if ( tmpCurIndex
< 0 ) {
243 if ( showDebug
== true ) {
244 System
.out
.println("END OF FILE.");
245 System
.out
.println();
250 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
251 /*System.out.println(tracefile);*/
253 tmpPrevIndex
= tmpCurIndex
;
254 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
);
255 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
256 /*System.out.println(marker);*/
258 // Timestamp is next but is presented in second.milisecond format, we have to split them
261 tmpPrevIndex
= tmpCurIndex
+1;
262 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
263 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
264 /*System.out.println(tmpSecond);*/
266 tmpPrevIndex
= tmpCurIndex
+1;
267 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
);
268 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
269 /*System.out.println(tmpNanosecond);*/
271 // We have enough information here to set the timestamp
272 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
273 /*System.out.println(eventTimestamp.toString());*/
275 // Next field is the reference
276 // A long string enclosed by parenthesis and ending with a comma
277 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
278 tmpPrevIndex
= tmpCurIndex
+1;
279 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
);
280 tmpPrevIndex
= tmpCurIndex
+1;
281 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
);
282 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
283 /*System.out.println(fullTracePath);*/
285 eventReference
.setValue(fullTracePath
);
286 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim();
287 /*System.out.println(traceName);*/
288 eventReference
.setTracepath(traceName
);
291 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
292 // They should be like the following :
293 // 4175, 4175, hal-acl-tool, , 4168,
296 tmpPrevIndex
= tmpCurIndex
+1;
297 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
299 tmpPrevIndex
= tmpCurIndex
+1;
300 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
302 tmpPrevIndex
= tmpCurIndex
+1;
303 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
305 tmpPrevIndex
= tmpCurIndex
+1;
306 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
308 tmpPrevIndex
= tmpCurIndex
+1;
309 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
311 tmpPrevIndex
= tmpCurIndex
+1;
312 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
314 // The next field is the CPU, in hexadecimal format
317 tmpPrevIndex
= tmpCurIndex
+1;
318 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
);
319 tmpPrevIndex
= tmpCurIndex
+2;
321 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
322 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
324 // Set the cpu number of trace if we found a "new" cpu
325 if ( cpuNumber
< (tmpCpu
+ 1) ) {
326 cpuNumber
= (int)(tmpCpu
+1);
328 /*System.out.println(tmpCpu);*/
331 // The last field is the parsed content
332 // It is enclosed by { }
334 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
336 // NOTE : it seems some state system events do not respect this format as they have no payload.
337 // We will create empty payload then.
338 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
);
339 if ( tmpIndex
!= -1 ) {
340 tmpPrevIndex
= tmpCurIndex
+1;
341 tmpCurIndex
= tmpIndex
;
342 tmpPrevIndex
= tmpCurIndex
+1;
343 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
);
344 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
346 // Now add each LttngField
347 boolean isDone
= false;
348 int tmpIndexBegin
= 0;
349 int tmpIndexEqual
= 0;
352 fieldsMap
= new HashMap
<String
, LttngEventField
>();
354 while ( isDone
== false ) {
355 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
);
356 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
);
357 if ( tmpIndexEnd
== -1 ) {
358 tmpIndexEnd
= parsedPayload
.length();
362 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
363 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim();
365 // Try to cast the payload into the correct type
367 payload
= Long
.parseLong((String
)payload
);
369 catch (NumberFormatException e
) { }
371 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
372 fieldsMap
.put(markerName
, tmpField
);
374 tmpIndexBegin
= tmpIndexEnd
+1;
378 fieldsMap
= new HashMap
<String
, LttngEventField
>();
383 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
384 fieldsMap
.put(markerName
, tmpField
);
387 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
389 // We now have what we need for the type
390 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
;
391 if ( traceTypes
.get(tmpTypeKey
) == null ) {
392 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
395 currentLttngEvent
.setContent(eventContent
);
396 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
398 returnedEvent
= currentLttngEvent
;
400 else if ( showDebug
== true ) {
401 System
.out
.println("NULL READING");
402 System
.out
.println();
403 returnedEvent
= null;
406 catch (Exception e
) {
407 System
.out
.println("Pos is :" + nbCharRead
);
408 if ( tmpContent
!= null ) {
409 System
.out
.println("Erroneous content is :" + tmpContent
);
414 returnedEvent
= null;
417 return returnedEvent
;
421 public ITmfLocation
<?
> getCurrentLocation() {
422 return new TmfLocation
<Long
>(nbCharRead
);
426 public LttngEvent
parseEvent(TmfContext context
) {
427 context
= seekLocation(context
.getLocation());
428 return parseMyNextEvent(context
);
432 public int getCpuNumber() {
439 // Redefine event to override method we know won't work with a Text tracefile
440 class TextLttngEvent
extends LttngEvent
{
442 public TextLttngEvent( TmfTrace
<LttngEvent
> parent
,
443 LttngTimestamp timestamp
,
444 LttngEventSource source
,
446 LttngEventContent content
,
447 LttngEventReference reference
)
449 super(parent
, timestamp
, source
, type
, content
, reference
, null);
452 public TextLttngEvent(TextLttngEvent oldEvent
) {
454 oldEvent
.getParentTrace(),
455 (LttngTimestamp
)oldEvent
.getTimestamp(),
456 (LttngEventSource
)oldEvent
.getSource(),
457 (LttngEventType
)oldEvent
.getType(),
458 (LttngEventContent
)oldEvent
.getContent(),
459 (LttngEventReference
)oldEvent
.getReference()
464 public JniEvent
convertEventTmfToJni() {
465 System
.out
.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format.");
470 public void updateJniEventReference(JniEvent newJniEventReference
) {
471 System
.out
.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null.");
476 class TextLttngEventContent
extends LttngEventContent
{
478 public TextLttngEventContent() {
482 public TextLttngEventContent(TextLttngEvent thisParent
) {
483 super(thisParent
, null);
486 public TextLttngEventContent(TextLttngEvent thisParent
, HashMap
<String
, LttngEventField
> thisContent
) {
487 super(thisParent
, thisContent
);
490 public TextLttngEventContent(TextLttngEventContent oldContent
) {
491 this( (TextLttngEvent
)oldContent
.fParentEvent
, oldContent
.getRawContent());
495 public LttngEventField
[] getFields() {
496 return getRawContent().values().toArray(new LttngEventField
[getRawContent().size()]);
500 public LttngEventField
getField(String name
) {
501 LttngEventField returnedField
= getRawContent().get(name
);
503 return returnedField
;
507 public LttngEventField
getField(int position
) {
508 LttngEventField returnedField
= null;
511 label
= fParentEvent
.getType().getLabel(position
);
512 returnedField
= this.getField(label
);
514 catch (TmfNoSuchFieldException e
) {
515 System
.out
.println("Invalid field position requested : " + position
+ ", ignoring (getField).");
518 return returnedField
;