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
.TmfCheckpoint
;
32 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfContext
;
33 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfLocation
;
34 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfTrace
;
36 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> {
37 private LttngTimestamp eventTimestamp
= null;
38 private LttngEventSource eventSource
= null;
39 private LttngEventType eventType
= null;
40 private TextLttngEventContent eventContent
= null;
41 private LttngEventReference eventReference
= null;
43 private TextLttngEvent currentLttngEvent
= null;
45 private HashMap
<String
, LttngEventType
> traceTypes
= null;
47 private String tracepath
= ""; //$NON-NLS-1$
48 private FileReader fr
= null;
49 private BufferedReader br
= null;
50 private Long nbCharRead
= 0L;
52 private int cpuNumber
= -1;
54 private boolean showDebug
= false;
56 public LTTngTextTrace(String path
) throws Exception
{
57 this(path
, true); // false);
60 public LTTngTextTrace(String path
, boolean skipIndexing
) throws Exception
{
61 super(path
, LttngEvent
.class, path
, 1, !skipIndexing
);
64 traceTypes
= new HashMap
<String
, LttngEventType
>();
66 eventTimestamp
= new LttngTimestamp();
67 eventSource
= new LttngEventSource();
68 eventType
= new LttngEventType();
69 eventContent
= new TextLttngEventContent(currentLttngEvent
);
70 eventReference
= new LttngEventReference(this.getName());
72 currentLttngEvent
= new TextLttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
);
73 eventContent
.setEvent(currentLttngEvent
);
75 if ( positionToFirstEvent() == false ) {
76 throw new IOException("Fail to position to the beginning of the trace"); //$NON-NLS-1$
79 fIndexPageSize
= 1000;
81 // Skip indexing if asked
82 // if ( skipIndexing == true ) {
83 fCheckpoints
.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation
<Long
>(0L)));
89 Long endTime
= currentLttngEvent
.getTimestamp().getValue();
90 positionToFirstEvent();
92 getNextEvent(new TmfContext(null, 0));
93 Long starTime
= currentLttngEvent
.getTimestamp().getValue();
94 positionToFirstEvent();
96 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
97 new LttngTimestamp(endTime
)
103 public LTTngTextTrace(LTTngTextTrace oldTrace
) throws Exception
{
104 this(oldTrace
.getPath(), true);
108 fCheckpoints
= oldTrace
.fCheckpoints
;
112 public LTTngTextTrace
copy() {
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()); //$NON-NLS-1$
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 (IOException 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)"); //$NON-NLS-1$
162 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
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)"); //$NON-NLS-1$
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
;
195 public TmfContext
seekLocation(double ratio
) {
196 // TODO Auto-generated method stub
201 public double getLocationRatio(ITmfLocation
<?
> location
) {
202 // TODO Auto-generated method stub
206 private LttngEvent
parseMyNextEvent(TmfContext context
) {
208 // All parsing variables declared here so to be able to print them into the catch if needed
209 String tmpContent
= null;
211 int tmpPrevIndex
= 0;
213 String tracefile
= ""; //$NON-NLS-1$
215 String marker
= ""; //$NON-NLS-1$
218 long tmpNanosecond
= 0;
220 String parsedPayload
= ""; //$NON-NLS-1$
221 String markerName
= ""; //$NON-NLS-1$
222 Object payload
= ""; //$NON-NLS-1$
224 HashMap
<String
, LttngEventField
> fieldsMap
= null;
226 LttngEvent returnedEvent
= null;
229 tmpContent
= br
.readLine();
231 if (tmpContent
!= null) {
233 // -1 is the skip the end of line (\n)
234 nbCharRead
+= (tmpContent
.length()+1);
236 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getRawContent() != null) ) {
237 currentLttngEvent
.getContent().emptyContent();
240 // EventSource is always the same for now :
241 eventSource
.setSourceId("Kernel Core"); //$NON-NLS-1$
244 // Tracefile and marker are first in the file
246 // kernel.syscall_entry:
247 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
250 // Evil exit case here : the two last line of the text dump does not contain "."
251 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
252 // Conclusion : this is ugly but fast.
253 if ( tmpCurIndex
< 0 ) {
254 if ( showDebug
== true ) {
255 System
.out
.println("END OF FILE."); //$NON-NLS-1$
256 System
.out
.println();
261 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
262 /*System.out.println(tracefile);*/
264 tmpPrevIndex
= tmpCurIndex
;
265 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
266 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
267 /*System.out.println(marker);*/
269 // Timestamp is next but is presented in second.milisecond format, we have to split them
272 tmpPrevIndex
= tmpCurIndex
+1;
273 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
274 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
275 /*System.out.println(tmpSecond);*/
277 tmpPrevIndex
= tmpCurIndex
+1;
278 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
279 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
280 /*System.out.println(tmpNanosecond);*/
282 // We have enough information here to set the timestamp
283 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
284 /*System.out.println(eventTimestamp.toString());*/
286 // Next field is the reference
287 // A long string enclosed by parenthesis and ending with a comma
288 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
289 tmpPrevIndex
= tmpCurIndex
+1;
290 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
291 tmpPrevIndex
= tmpCurIndex
+1;
292 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
293 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
294 /*System.out.println(fullTracePath);*/
296 eventReference
.setValue(fullTracePath
);
297 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
298 /*System.out.println(traceName);*/
299 eventReference
.setTracepath(traceName
);
302 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
303 // They should be like the following :
304 // 4175, 4175, hal-acl-tool, , 4168,
307 tmpPrevIndex
= tmpCurIndex
+1;
308 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
310 tmpPrevIndex
= tmpCurIndex
+1;
311 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
313 tmpPrevIndex
= tmpCurIndex
+1;
314 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
316 tmpPrevIndex
= tmpCurIndex
+1;
317 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
319 tmpPrevIndex
= tmpCurIndex
+1;
320 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
322 tmpPrevIndex
= tmpCurIndex
+1;
323 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
325 // The next field is the CPU, in hexadecimal format
328 tmpPrevIndex
= tmpCurIndex
+1;
329 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
330 tmpPrevIndex
= tmpCurIndex
+2;
332 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
333 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
335 // Set the cpu number of trace if we found a "new" cpu
336 if ( cpuNumber
< (tmpCpu
+ 1) ) {
337 cpuNumber
= (int)(tmpCpu
+1);
339 /*System.out.println(tmpCpu);*/
342 // The last field is the parsed content
343 // It is enclosed by { }
345 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
347 // NOTE : it seems some state system events do not respect this format as they have no payload.
348 // We will create empty payload then.
349 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
350 if ( tmpIndex
!= -1 ) {
351 tmpPrevIndex
= tmpCurIndex
+1;
352 tmpCurIndex
= tmpIndex
;
353 tmpPrevIndex
= tmpCurIndex
+1;
354 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
355 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
357 // Now add each LttngField
358 boolean isDone
= false;
359 int tmpIndexBegin
= 0;
360 int tmpIndexEqual
= 0;
363 fieldsMap
= new HashMap
<String
, LttngEventField
>();
365 while ( isDone
== false ) {
366 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
); //$NON-NLS-1$
367 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
); //$NON-NLS-1$
368 if ( tmpIndexEnd
== -1 ) {
369 tmpIndexEnd
= parsedPayload
.length();
373 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
374 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
376 // Try to cast the payload into the correct type
378 payload
= Long
.parseLong((String
)payload
);
380 catch (NumberFormatException e
) { }
382 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
383 fieldsMap
.put(markerName
, tmpField
);
385 tmpIndexBegin
= tmpIndexEnd
+1;
389 fieldsMap
= new HashMap
<String
, LttngEventField
>();
391 markerName
= ""; //$NON-NLS-1$
392 payload
= ""; //$NON-NLS-1$
394 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
395 fieldsMap
.put(markerName
, tmpField
);
398 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
400 // We now have what we need for the type
401 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
402 if ( traceTypes
.get(tmpTypeKey
) == null ) {
403 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
406 currentLttngEvent
.setContent(eventContent
);
407 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
409 returnedEvent
= currentLttngEvent
;
411 else if ( showDebug
== true ) {
412 System
.out
.println("NULL READING"); //$NON-NLS-1$
413 System
.out
.println();
414 returnedEvent
= null;
417 catch (Exception e
) {
418 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
419 if ( tmpContent
!= null ) {
420 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
425 returnedEvent
= null;
428 return returnedEvent
;
432 public ITmfLocation
<?
> getCurrentLocation() {
433 return new TmfLocation
<Long
>(nbCharRead
);
437 public LttngEvent
parseEvent(TmfContext context
) {
438 context
= seekLocation(context
.getLocation());
439 return parseMyNextEvent(context
);
443 public int getCpuNumber() {
450 // Redefine event to override method we know won't work with a Text tracefile
451 class TextLttngEvent
extends LttngEvent
{
453 public TextLttngEvent( TmfTrace
<LttngEvent
> parent
,
454 LttngTimestamp timestamp
,
455 LttngEventSource source
,
457 LttngEventContent content
,
458 LttngEventReference reference
)
460 super(parent
, timestamp
, source
, type
, content
, reference
, null);
463 @SuppressWarnings("unchecked")
464 public TextLttngEvent(TextLttngEvent oldEvent
) {
466 (TmfTrace
<LttngEvent
>) oldEvent
.getParentTrace(),
467 (LttngTimestamp
)oldEvent
.getTimestamp(),
468 (LttngEventSource
)oldEvent
.getSource(),
469 (LttngEventType
)oldEvent
.getType(),
470 (LttngEventContent
)oldEvent
.getContent(),
471 (LttngEventReference
)oldEvent
.getReference()
476 public JniEvent
convertEventTmfToJni() {
477 System
.out
.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
482 public void updateJniEventReference(JniEvent newJniEventReference
) {
483 System
.out
.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
488 class TextLttngEventContent
extends LttngEventContent
{
490 public TextLttngEventContent() {
494 public TextLttngEventContent(TextLttngEvent thisParent
) {
495 super(thisParent
, null);
498 public TextLttngEventContent(TextLttngEvent thisParent
, HashMap
<String
, LttngEventField
> thisContent
) {
499 super(thisParent
, thisContent
);
502 public TextLttngEventContent(TextLttngEventContent oldContent
) {
503 this( (TextLttngEvent
)oldContent
.fParentEvent
, oldContent
.getRawContent());
507 public LttngEventField
[] getFields() {
508 return getRawContent().values().toArray(new LttngEventField
[getRawContent().size()]);
512 public LttngEventField
getField(String name
) {
513 LttngEventField returnedField
= getRawContent().get(name
);
515 return returnedField
;
519 public LttngEventField
getField(int position
) {
520 LttngEventField returnedField
= null;
523 label
= fParentEvent
.getType().getLabel(position
);
524 returnedField
= this.getField(label
);
526 catch (TmfNoSuchFieldException e
) {
527 System
.out
.println("Invalid field position requested : " + position
+ ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
530 return returnedField
;