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
.core
.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
.core
.event
.LttngEvent
;
21 import org
.eclipse
.linuxtools
.lttng
.core
.event
.LttngEventContent
;
22 import org
.eclipse
.linuxtools
.lttng
.core
.event
.LttngEventField
;
23 import org
.eclipse
.linuxtools
.lttng
.core
.event
.LttngEventType
;
24 import org
.eclipse
.linuxtools
.lttng
.core
.event
.LttngTimestamp
;
25 import org
.eclipse
.linuxtools
.lttng
.jni
.JniEvent
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfCheckpoint
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfLocation
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
33 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> {
34 private LttngTimestamp eventTimestamp
= null;
35 private String eventSource
= null;
36 private LttngEventType eventType
= null;
37 private TextLttngEventContent eventContent
= null;
38 private String eventReference
= null;
40 private TextLttngEvent currentLttngEvent
= null;
42 private HashMap
<String
, LttngEventType
> traceTypes
= null;
44 private String tracepath
= ""; //$NON-NLS-1$
45 private FileReader fr
= null;
46 private BufferedReader br
= null;
47 private Long nbCharRead
= 0L;
49 private int cpuNumber
= -1;
51 private boolean showDebug
= false;
53 public LTTngTextTrace(String path
) throws Exception
{
54 this(path
, true); // false);
57 public LTTngTextTrace(String path
, boolean skipIndexing
) throws Exception
{
58 super(path
, LttngEvent
.class, path
, 1, !skipIndexing
);
61 traceTypes
= new HashMap
<String
, LttngEventType
>();
63 eventTimestamp
= new LttngTimestamp();
64 eventSource
= "Kernel Core"; //$NON-NLS-1$
65 eventType
= new LttngEventType();
66 eventContent
= new TextLttngEventContent(currentLttngEvent
);
67 eventReference
= getName();
69 currentLttngEvent
= new TextLttngEvent(this, eventTimestamp
, eventSource
, eventType
, eventContent
, eventReference
);
70 eventContent
.setEvent(currentLttngEvent
);
72 if ( positionToFirstEvent() == false ) {
73 throw new IOException("Fail to position to the beginning of the trace"); //$NON-NLS-1$
76 fIndexPageSize
= 1000;
78 // Skip indexing if asked
79 // if ( skipIndexing == true ) {
80 fCheckpoints
.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation
<Long
>(0L)));
86 Long endTime
= currentLttngEvent
.getTimestamp().getValue();
87 positionToFirstEvent();
89 getNextEvent(new TmfContext(null, 0));
90 Long starTime
= currentLttngEvent
.getTimestamp().getValue();
91 positionToFirstEvent();
93 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
94 new LttngTimestamp(endTime
)
100 public LTTngTextTrace(LTTngTextTrace oldTrace
) throws Exception
{
101 this(oldTrace
.getPath(), true);
105 fCheckpoints
= oldTrace
.fCheckpoints
;
109 public LTTngTextTrace
copy() {
111 LTTngTextTrace returnedTrace
= null;
114 returnedTrace
= new LTTngTextTrace(this);
116 catch (Exception e
) {
117 System
.out
.println("ERROR : Could not create LTTngTextTrace copy (createTraceCopy).\nError is : " + e
.getStackTrace()); //$NON-NLS-1$
120 return returnedTrace
;
123 private boolean positionToFirstEvent() {
125 boolean isSuccessful
= true;
133 fr
= new FileReader(tracepath
);
134 br
= new BufferedReader(fr
);
136 // Skip the 2 lines header
140 // Make sure the event time is consistent
141 eventTimestamp
.setValue(0L);
143 catch (IOException e
) {
144 isSuccessful
= false;
150 private void skipToPosition(TmfLocation
<Long
> skip
) {
152 long skipPosition
= skip
.getLocation();
153 if ( skipPosition
< 0 ) {
157 if ( showDebug
== true ) {
158 System
.out
.println("skipToPosition(Long skipPosition)"); //$NON-NLS-1$
159 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
160 System
.out
.println();
162 positionToFirstEvent();
163 long nbSkipped
= br
.skip(skipPosition
);
164 if ( nbSkipped
!= skipPosition
) {
165 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); //$NON-NLS-1$
168 nbCharRead
= skipPosition
;
170 catch (Exception e
) {
176 @SuppressWarnings("unchecked")
177 public TmfContext
seekLocation(ITmfLocation
<?
> location
) {
178 if (location
== null) {
179 location
= new TmfLocation
<Long
>(0L);
182 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
)) {
183 skipToPosition((TmfLocation
<Long
>) location
);
186 TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
188 return tmpTraceContext
;
192 public TmfContext
seekLocation(double ratio
) {
193 // TODO Auto-generated method stub
198 public double getLocationRatio(ITmfLocation
<?
> location
) {
199 // TODO Auto-generated method stub
203 private LttngEvent
parseMyNextEvent(TmfContext context
) {
205 // All parsing variables declared here so to be able to print them into the catch if needed
206 String tmpContent
= null;
208 int tmpPrevIndex
= 0;
210 String tracefile
= ""; //$NON-NLS-1$
212 String marker
= ""; //$NON-NLS-1$
215 long tmpNanosecond
= 0;
217 String parsedPayload
= ""; //$NON-NLS-1$
218 String markerName
= ""; //$NON-NLS-1$
219 Object payload
= ""; //$NON-NLS-1$
221 HashMap
<String
, LttngEventField
> fieldsMap
= null;
223 LttngEvent returnedEvent
= null;
226 tmpContent
= br
.readLine();
228 if (tmpContent
!= null) {
230 // -1 is the skip the end of line (\n)
231 nbCharRead
+= (tmpContent
.length()+1);
233 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getMapContent() != null) ) {
234 currentLttngEvent
.getContent().emptyContent();
237 // Tracefile and marker are first in the file
239 // kernel.syscall_entry:
240 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
243 // Evil exit case here : the two last line of the text dump does not contain "."
244 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
245 // Conclusion : this is ugly but fast.
246 if ( tmpCurIndex
< 0 ) {
247 if ( showDebug
== true ) {
248 System
.out
.println("END OF FILE."); //$NON-NLS-1$
249 System
.out
.println();
254 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
255 /*System.out.println(tracefile);*/
257 tmpPrevIndex
= tmpCurIndex
;
258 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
259 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
260 /*System.out.println(marker);*/
262 // Timestamp is next but is presented in second.milisecond format, we have to split them
265 tmpPrevIndex
= tmpCurIndex
+1;
266 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
267 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
268 /*System.out.println(tmpSecond);*/
270 tmpPrevIndex
= tmpCurIndex
+1;
271 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
272 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
273 /*System.out.println(tmpNanosecond);*/
275 // We have enough information here to set the timestamp
276 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
277 /*System.out.println(eventTimestamp.toString());*/
279 // Next field is the reference
280 // A long string enclosed by parenthesis and ending with a comma
281 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
282 tmpPrevIndex
= tmpCurIndex
+1;
283 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
284 tmpPrevIndex
= tmpCurIndex
+1;
285 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
286 String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
287 /*System.out.println(fullTracePath);*/
289 String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
290 /*System.out.println(traceName);*/
291 eventReference
= traceName
;
292 currentLttngEvent
.setReference(traceName
);
295 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
296 // They should be like the following :
297 // 4175, 4175, hal-acl-tool, , 4168,
300 tmpPrevIndex
= tmpCurIndex
+1;
301 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
303 tmpPrevIndex
= tmpCurIndex
+1;
304 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
306 tmpPrevIndex
= tmpCurIndex
+1;
307 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
309 tmpPrevIndex
= tmpCurIndex
+1;
310 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
312 tmpPrevIndex
= tmpCurIndex
+1;
313 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
315 tmpPrevIndex
= tmpCurIndex
+1;
316 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
318 // The next field is the CPU, in hexadecimal format
321 tmpPrevIndex
= tmpCurIndex
+1;
322 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
323 tmpPrevIndex
= tmpCurIndex
+2;
325 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
326 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
328 // Set the cpu number of trace if we found a "new" cpu
329 if ( cpuNumber
< (tmpCpu
+ 1) ) {
330 cpuNumber
= (int)(tmpCpu
+1);
332 /*System.out.println(tmpCpu);*/
335 // The last field is the parsed content
336 // It is enclosed by { }
338 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
340 // NOTE : it seems some state system events do not respect this format as they have no payload.
341 // We will create empty payload then.
342 int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
343 if ( tmpIndex
!= -1 ) {
344 tmpPrevIndex
= tmpCurIndex
+1;
345 tmpCurIndex
= tmpIndex
;
346 tmpPrevIndex
= tmpCurIndex
+1;
347 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
348 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
350 // Now add each LttngField
351 boolean isDone
= false;
352 int tmpIndexBegin
= 0;
353 int tmpIndexEqual
= 0;
356 fieldsMap
= new HashMap
<String
, LttngEventField
>();
358 while ( isDone
== false ) {
359 tmpIndexEqual
= parsedPayload
.indexOf("=", (int)tmpIndexBegin
); //$NON-NLS-1$
360 tmpIndexEnd
= parsedPayload
.indexOf(", ", (int)tmpIndexEqual
); //$NON-NLS-1$
361 if ( tmpIndexEnd
== -1 ) {
362 tmpIndexEnd
= parsedPayload
.length();
366 markerName
= parsedPayload
.substring((int)tmpIndexBegin
, (int)tmpIndexEqual
-1 ).trim();
367 payload
= ((String
)parsedPayload
.substring((int)tmpIndexEqual
+1, (int)tmpIndexEnd
)).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
369 // Try to cast the payload into the correct type
371 payload
= Long
.parseLong((String
)payload
);
373 catch (NumberFormatException e
) { }
375 LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
376 fieldsMap
.put(markerName
, tmpField
);
378 tmpIndexBegin
= tmpIndexEnd
+1;
382 fieldsMap
= new HashMap
<String
, LttngEventField
>();
384 markerName
= ""; //$NON-NLS-1$
385 payload
= ""; //$NON-NLS-1$
387 LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
388 fieldsMap
.put(markerName
, tmpField
);
391 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
393 // We now have what we need for the type
394 String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
395 if ( traceTypes
.get(tmpTypeKey
) == null ) {
396 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
399 currentLttngEvent
.setContent(eventContent
);
400 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
402 returnedEvent
= currentLttngEvent
;
404 else if ( showDebug
== true ) {
405 System
.out
.println("NULL READING"); //$NON-NLS-1$
406 System
.out
.println();
407 returnedEvent
= null;
410 catch (Exception e
) {
411 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
412 if ( tmpContent
!= null ) {
413 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
418 returnedEvent
= null;
421 return returnedEvent
;
425 public ITmfLocation
<?
> getCurrentLocation() {
426 return new TmfLocation
<Long
>(nbCharRead
);
430 public LttngEvent
parseEvent(TmfContext context
) {
431 context
= seekLocation(context
.getLocation());
432 return parseMyNextEvent(context
);
436 public int getCpuNumber() {
443 // Redefine event to override method we know won't work with a Text tracefile
444 class TextLttngEvent
extends LttngEvent
{
446 public TextLttngEvent( TmfTrace
<LttngEvent
> parent
,
447 LttngTimestamp timestamp
,
450 LttngEventContent content
,
453 super(parent
, timestamp
, source
, type
, content
, reference
, null);
456 @SuppressWarnings("unchecked")
457 public TextLttngEvent(TextLttngEvent oldEvent
) {
459 (TmfTrace
<LttngEvent
>) oldEvent
.getTrace(),
460 (LttngTimestamp
)oldEvent
.getTimestamp(),
461 oldEvent
.getSource(),
462 (LttngEventType
)oldEvent
.getType(),
463 (LttngEventContent
)oldEvent
.getContent(),
464 oldEvent
.getReference()
469 public JniEvent
convertEventTmfToJni() {
470 System
.out
.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
475 public void updateJniEventReference(JniEvent newJniEventReference
) {
476 System
.out
.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
481 class TextLttngEventContent
extends LttngEventContent
{
483 public TextLttngEventContent() {
487 public TextLttngEventContent(TextLttngEvent thisParent
) {
488 super(thisParent
, null);
491 public TextLttngEventContent(TextLttngEvent thisParent
, HashMap
<String
, LttngEventField
> thisContent
) {
492 super(thisParent
, thisContent
);
495 public TextLttngEventContent(TextLttngEventContent oldContent
) {
496 this(((TextLttngEvent
) oldContent
.getEvent()), oldContent
.getMapContent());
500 public LttngEventField
[] getFields() {
501 return getMapContent().values().toArray(new LttngEventField
[getMapContent().size()]);
505 public LttngEventField
getField(String name
) {
506 LttngEventField returnedField
= getMapContent().get(name
);
508 return returnedField
;
512 public LttngEventField
getField(int position
) {
513 LttngEventField returnedField
= null;
516 label
= getEvent().getType().getFieldName(position
);
517 returnedField
= this.getField(label
);
519 // catch (TmfNoSuchFieldException e) {
520 // System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
523 return returnedField
;