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
.TmfTimeRange
;
29 import org
.eclipse
.linuxtools
.tmf
.request
.TmfDataRequest
;
30 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfContext
;
31 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfLocation
;
32 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfTrace
;
33 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfCheckpoint
;
34 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfContext
;
35 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfLocation
;
36 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfTrace
;
38 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> implements ITmfTrace
{
39 private LttngTimestamp eventTimestamp
= null;
40 private LttngEventSource eventSource
= null;
41 private LttngEventType eventType
= null;
42 private TextLttngEventContent eventContent
= null;
43 private LttngEventReference eventReference
= null;
45 private TextLttngEvent currentLttngEvent
= null;
47 private HashMap
<String
, LttngEventType
> traceTypes
= null;
49 private String tracepath
= "";
50 private FileReader fr
= null;
51 private BufferedReader br
= null;
52 private Long nbCharRead
= 0L;
54 private int cpuNumber
= -1;
56 private boolean showDebug
= true;
58 public LTTngTextTrace(String path
) throws Exception
{
62 public LTTngTextTrace(String path
, boolean skipIndexing
) throws Exception
{
63 super(LttngEvent
.class, path
, 1);
66 traceTypes
= new HashMap
<String
, LttngEventType
>();
68 eventTimestamp
= new LttngTimestamp();
69 eventSource
= new LttngEventSource();
70 eventType
= new LttngEventType();
71 eventContent
= new TextLttngEventContent(currentLttngEvent
);
72 eventReference
= new LttngEventReference(this.getName());
74 currentLttngEvent
= new TextLttngEvent(eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
);
75 eventContent
.setEvent(currentLttngEvent
);
77 if ( positionToFirstEvent() == false ) {
78 throw new IOException("Fail to position to the beginning of the trace");
81 fIndexPageSize
= 1000;
83 // Skip indexing if asked
84 if ( skipIndexing
== true ) {
85 fCheckpoints
.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation
<Long
>(0L)));
91 Long endTime
= currentLttngEvent
.getTimestamp().getValue();
92 positionToFirstEvent();
94 getNextEvent(new TmfContext(null, 0));
95 Long starTime
= currentLttngEvent
.getTimestamp().getValue();
96 positionToFirstEvent();
98 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
99 new LttngTimestamp(endTime
)
105 private LTTngTextTrace(LTTngTrace oldStream
) throws Exception
{
106 super(LttngEvent
.class, null);
107 throw new Exception("Copy constructor should never be use with a LTTngTrace!");
110 private boolean positionToFirstEvent() {
112 boolean isSuccessful
= true;
120 fr
= new FileReader(tracepath
);
121 br
= new BufferedReader(fr
);
123 // Skip the 2 lines header
127 // Make sure the event time is consistent
128 eventTimestamp
.setValue(0L);
130 catch (Exception e
) {
131 isSuccessful
= false;
137 private void skipToPosition(TmfLocation
<Long
> skip
) {
139 long skipPosition
= skip
.getValue();
140 if ( skipPosition
< 0 ) {
144 if ( showDebug
== true ) {
145 System
.out
.println("skipToPosition(Long skipPosition)");
146 System
.out
.println("\tSkipping to : " + skipPosition
);
147 System
.out
.println();
149 positionToFirstEvent();
150 br
.skip(skipPosition
);
152 nbCharRead
= skipPosition
;
154 catch (Exception e
) {
159 @SuppressWarnings("unchecked")
160 public TmfContext
seekLocation(ITmfLocation location
) {
162 if (location
== null) {
163 location
= new TmfLocation
<Long
>(0L);
166 if (!((TmfLocation
<Long
>) location
).getValue().equals(nbCharRead
)) {
167 skipToPosition((TmfLocation
<Long
>) location
);
170 TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
172 return tmpTraceContext
;
175 private LttngEvent
parseMyNextEvent(TmfContext context
) {
177 // All parsing variables declared here so to be able to print them into the catch if needed
178 String tmpContent
= null;
180 int tmpPrevIndex
= 0;
182 String tracefile
= "";
187 long tmpNanosecond
= 0;
189 String parsedPayload
= "";
190 String markerName
= "";
193 HashMap
<String
, LttngEventField
> fieldsMap
= null;
195 LttngEvent returnedEvent
= null;
198 tmpContent
= br
.readLine();
200 if (tmpContent
!= null) {
202 // -1 is the skip the end of line (\n)
203 nbCharRead
+= (tmpContent
.length()+1);
205 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getRawContent() != null) ) {
206 currentLttngEvent
.getContent().emptyContent();
209 // EventSource is always the same for now :
210 eventSource
.setSourceId("Kernel Core");
213 // Tracefile and marker are first in the file
215 // kernel.syscall_entry:
216 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
219 // Evil exit case here : the two last line of the text dump does not contain "."
220 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
221 // Conclusion : this is ugly but fast.
222 if ( tmpCurIndex
< 0 ) {
223 if ( showDebug
== true ) {
224 System
.out
.println("END OF FILE.");
225 System
.out
.println();
230 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
231 /*System.out.println(tracefile);*/
233 tmpPrevIndex
= tmpCurIndex
;
234 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
);
235 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
236 /*System.out.println(marker);*/
238 // Timestamp is next but is presented in second.milisecond format, we have to split them
241 tmpPrevIndex
= tmpCurIndex
+1;
242 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
);
243 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
244 /*System.out.println(tmpSecond);*/
246 tmpPrevIndex
= tmpCurIndex
+1;
247 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
);
248 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
249 /*System.out.println(tmpNanosecond);*/
251 // We have enough information here to set the timestamp
252 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
253 /*System.out.println(eventTimestamp.toString());*/
255 // Next field is the reference
256 // A long string enclosed by parenthesis and ending with a comma
257 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
258 tmpPrevIndex
= tmpCurIndex
+1;
259 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
);
260 tmpPrevIndex
= tmpCurIndex
+1;
261 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
);
262 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
263 /*System.out.println(fullTracePath);*/
265 eventReference
.setValue(fullTracePath
);
266 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim();
267 /*System.out.println(traceName);*/
268 eventReference
.setTracepath(traceName
);
271 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
272 // They should be like the following :
273 // 4175, 4175, hal-acl-tool, , 4168,
276 tmpPrevIndex
= tmpCurIndex
+1;
277 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
279 tmpPrevIndex
= tmpCurIndex
+1;
280 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
282 tmpPrevIndex
= tmpCurIndex
+1;
283 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
285 tmpPrevIndex
= tmpCurIndex
+1;
286 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
288 tmpPrevIndex
= tmpCurIndex
+1;
289 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
291 tmpPrevIndex
= tmpCurIndex
+1;
292 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
294 // The next field is the CPU, in hexadecimal format
297 tmpPrevIndex
= tmpCurIndex
+1;
298 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
);
299 tmpPrevIndex
= tmpCurIndex
+2;
301 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
);
302 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
304 // Set the cpu number of trace if we found a "new" cpu
305 if ( cpuNumber
< (tmpCpu
+ 1) ) {
306 cpuNumber
= (int)(tmpCpu
+1);
308 /*System.out.println(tmpCpu);*/
311 // The last field is the parsed content
312 // It is enclosed by { }
314 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
316 // NOTE : it seems some state system events do not respect this format as they have no payload.
317 // We will create empty payload then.
318 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
);
319 if ( tmpIndex
!= -1 ) {
320 tmpPrevIndex
= tmpCurIndex
+1;
321 tmpCurIndex
= tmpIndex
;
322 tmpPrevIndex
= tmpCurIndex
+1;
323 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
);
324 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
326 // Now add each LttngField
327 boolean isDone
= false;
328 int tmpIndexBegin
= 0;
329 int tmpIndexEqual
= 0;
332 fieldsMap
= new HashMap
<String
, LttngEventField
>();
334 while ( isDone
== false ) {
335 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
);
336 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
);
337 if ( tmpIndexEnd
== -1 ) {
338 tmpIndexEnd
= parsedPayload
.length();
342 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
343 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim();
345 // Try to cast the payload into the correct type
347 payload
= Long
.parseLong((String
)payload
);
349 catch (NumberFormatException e
) { }
351 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
352 fieldsMap
.put(markerName
, tmpField
);
354 tmpIndexBegin
= tmpIndexEnd
+1;
358 fieldsMap
= new HashMap
<String
, LttngEventField
>();
363 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
364 fieldsMap
.put(markerName
, tmpField
);
367 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
369 // We now have what we need for the type
370 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
;
371 if ( traceTypes
.get(tmpTypeKey
) == null ) {
372 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
375 currentLttngEvent
.setContent(eventContent
);
376 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
378 returnedEvent
= currentLttngEvent
;
380 else if ( showDebug
== true ) {
381 System
.out
.println("NULL READING");
382 System
.out
.println();
383 returnedEvent
= null;
386 catch (Exception e
) {
387 System
.out
.println("Pos is :" + nbCharRead
);
388 if ( tmpContent
!= null ) {
389 System
.out
.println("Erroneous content is :" + tmpContent
);
394 returnedEvent
= null;
397 return returnedEvent
;
401 public ITmfLocation
getCurrentLocation() {
402 return new TmfLocation
<Long
>(nbCharRead
);
406 public LttngEvent
parseEvent(TmfContext context
) {
407 context
= seekLocation(context
.getLocation());
408 return parseMyNextEvent(context
);
412 public int getCpuNumber() {
417 public ITmfContext
setContext(TmfDataRequest
<LttngEvent
> request
) {
418 // TODO Auto-generated method stub
425 // Redefine event to override method we know won't work with a Text tracefile
426 class TextLttngEvent
extends LttngEvent
{
428 public TextLttngEvent( LttngTimestamp timestamp
,
429 LttngEventSource source
,
431 LttngEventContent content
,
432 LttngEventReference reference
)
434 super(timestamp
, source
, type
, content
, reference
, null);
437 public TextLttngEvent(TextLttngEvent oldEvent
) {
439 (LttngTimestamp
)oldEvent
.getTimestamp(),
440 (LttngEventSource
)oldEvent
.getSource(),
441 (LttngEventType
)oldEvent
.getType(),
442 (LttngEventContent
)oldEvent
.getContent(),
443 (LttngEventReference
)oldEvent
.getReference()
448 public JniEvent
convertEventTmfToJni() {
449 System
.out
.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format.");
454 public void updateJniEventReference(JniEvent newJniEventReference
) {
455 System
.out
.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null.");
460 class TextLttngEventContent
extends LttngEventContent
{
462 public TextLttngEventContent() {
466 public TextLttngEventContent(TextLttngEvent thisParent
) {
467 super(thisParent
, null);
470 public TextLttngEventContent(TextLttngEvent thisParent
, HashMap
<String
, LttngEventField
> thisContent
) {
471 super(thisParent
, thisContent
);
474 public TextLttngEventContent(TextLttngEventContent oldContent
) {
475 this( (TextLttngEvent
)oldContent
.fParentEvent
, oldContent
.getRawContent());
479 public LttngEventField
[] getFields() {
480 return getRawContent().values().toArray(new LttngEventField
[getRawContent().size()]);
484 public LttngEventField
getField(String name
) {
485 LttngEventField returnedField
= getRawContent().get(name
);
487 return returnedField
;
491 public LttngEventField
getField(int position
) {
492 LttngEventField returnedField
= null;
493 String label
= fParentEvent
.getType().getLabel(position
);
495 if ( label
!= null ) {
496 returnedField
= this.getField(label
);
499 return returnedField
;