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
= ""; //$NON-NLS-1$
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, !skipIndexing
);
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"); //$NON-NLS-1$
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()); //$NON-NLS-1$
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)"); //$NON-NLS-1$
163 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
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)"); //$NON-NLS-1$
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
;
196 public TmfContext
seekLocation(double ratio
) {
197 // TODO Auto-generated method stub
202 public double getLocationRatio(ITmfLocation
<?
> location
) {
203 // TODO Auto-generated method stub
207 private LttngEvent
parseMyNextEvent(TmfContext context
) {
209 // All parsing variables declared here so to be able to print them into the catch if needed
210 String tmpContent
= null;
212 int tmpPrevIndex
= 0;
214 String tracefile
= ""; //$NON-NLS-1$
216 String marker
= ""; //$NON-NLS-1$
219 long tmpNanosecond
= 0;
221 String parsedPayload
= ""; //$NON-NLS-1$
222 String markerName
= ""; //$NON-NLS-1$
223 Object payload
= ""; //$NON-NLS-1$
225 HashMap
<String
, LttngEventField
> fieldsMap
= null;
227 LttngEvent returnedEvent
= null;
230 tmpContent
= br
.readLine();
232 if (tmpContent
!= null) {
234 // -1 is the skip the end of line (\n)
235 nbCharRead
+= (tmpContent
.length()+1);
237 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getRawContent() != null) ) {
238 currentLttngEvent
.getContent().emptyContent();
241 // EventSource is always the same for now :
242 eventSource
.setSourceId("Kernel Core"); //$NON-NLS-1$
245 // Tracefile and marker are first in the file
247 // kernel.syscall_entry:
248 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
251 // Evil exit case here : the two last line of the text dump does not contain "."
252 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
253 // Conclusion : this is ugly but fast.
254 if ( tmpCurIndex
< 0 ) {
255 if ( showDebug
== true ) {
256 System
.out
.println("END OF FILE."); //$NON-NLS-1$
257 System
.out
.println();
262 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
263 /*System.out.println(tracefile);*/
265 tmpPrevIndex
= tmpCurIndex
;
266 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
267 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
268 /*System.out.println(marker);*/
270 // Timestamp is next but is presented in second.milisecond format, we have to split them
273 tmpPrevIndex
= tmpCurIndex
+1;
274 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
275 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
276 /*System.out.println(tmpSecond);*/
278 tmpPrevIndex
= tmpCurIndex
+1;
279 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
280 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
281 /*System.out.println(tmpNanosecond);*/
283 // We have enough information here to set the timestamp
284 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
285 /*System.out.println(eventTimestamp.toString());*/
287 // Next field is the reference
288 // A long string enclosed by parenthesis and ending with a comma
289 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
290 tmpPrevIndex
= tmpCurIndex
+1;
291 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
292 tmpPrevIndex
= tmpCurIndex
+1;
293 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
294 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
295 /*System.out.println(fullTracePath);*/
297 eventReference
.setValue(fullTracePath
);
298 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
299 /*System.out.println(traceName);*/
300 eventReference
.setTracepath(traceName
);
303 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
304 // They should be like the following :
305 // 4175, 4175, hal-acl-tool, , 4168,
308 tmpPrevIndex
= tmpCurIndex
+1;
309 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
311 tmpPrevIndex
= tmpCurIndex
+1;
312 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
314 tmpPrevIndex
= tmpCurIndex
+1;
315 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
317 tmpPrevIndex
= tmpCurIndex
+1;
318 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
320 tmpPrevIndex
= tmpCurIndex
+1;
321 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
323 tmpPrevIndex
= tmpCurIndex
+1;
324 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
326 // The next field is the CPU, in hexadecimal format
329 tmpPrevIndex
= tmpCurIndex
+1;
330 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
331 tmpPrevIndex
= tmpCurIndex
+2;
333 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
334 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
336 // Set the cpu number of trace if we found a "new" cpu
337 if ( cpuNumber
< (tmpCpu
+ 1) ) {
338 cpuNumber
= (int)(tmpCpu
+1);
340 /*System.out.println(tmpCpu);*/
343 // The last field is the parsed content
344 // It is enclosed by { }
346 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
348 // NOTE : it seems some state system events do not respect this format as they have no payload.
349 // We will create empty payload then.
350 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
351 if ( tmpIndex
!= -1 ) {
352 tmpPrevIndex
= tmpCurIndex
+1;
353 tmpCurIndex
= tmpIndex
;
354 tmpPrevIndex
= tmpCurIndex
+1;
355 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
356 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
358 // Now add each LttngField
359 boolean isDone
= false;
360 int tmpIndexBegin
= 0;
361 int tmpIndexEqual
= 0;
364 fieldsMap
= new HashMap
<String
, LttngEventField
>();
366 while ( isDone
== false ) {
367 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
); //$NON-NLS-1$
368 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
); //$NON-NLS-1$
369 if ( tmpIndexEnd
== -1 ) {
370 tmpIndexEnd
= parsedPayload
.length();
374 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
375 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
377 // Try to cast the payload into the correct type
379 payload
= Long
.parseLong((String
)payload
);
381 catch (NumberFormatException e
) { }
383 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
384 fieldsMap
.put(markerName
, tmpField
);
386 tmpIndexBegin
= tmpIndexEnd
+1;
390 fieldsMap
= new HashMap
<String
, LttngEventField
>();
392 markerName
= ""; //$NON-NLS-1$
393 payload
= ""; //$NON-NLS-1$
395 LttngEventField tmpField
= new LttngEventField(eventContent
, markerName
, payload
);
396 fieldsMap
.put(markerName
, tmpField
);
399 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
401 // We now have what we need for the type
402 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
403 if ( traceTypes
.get(tmpTypeKey
) == null ) {
404 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
407 currentLttngEvent
.setContent(eventContent
);
408 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
410 returnedEvent
= currentLttngEvent
;
412 else if ( showDebug
== true ) {
413 System
.out
.println("NULL READING"); //$NON-NLS-1$
414 System
.out
.println();
415 returnedEvent
= null;
418 catch (Exception e
) {
419 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
420 if ( tmpContent
!= null ) {
421 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
426 returnedEvent
= null;
429 return returnedEvent
;
433 public ITmfLocation
<?
> getCurrentLocation() {
434 return new TmfLocation
<Long
>(nbCharRead
);
438 public LttngEvent
parseEvent(TmfContext context
) {
439 context
= seekLocation(context
.getLocation());
440 return parseMyNextEvent(context
);
444 public int getCpuNumber() {
451 // Redefine event to override method we know won't work with a Text tracefile
452 class TextLttngEvent
extends LttngEvent
{
454 public TextLttngEvent( TmfTrace
<LttngEvent
> parent
,
455 LttngTimestamp timestamp
,
456 LttngEventSource source
,
458 LttngEventContent content
,
459 LttngEventReference reference
)
461 super(parent
, timestamp
, source
, type
, content
, reference
, null);
464 public TextLttngEvent(TextLttngEvent oldEvent
) {
466 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
;