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
.internal
.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
.core
.resources
.IResource
;
21 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEvent
;
22 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventContent
;
23 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventField
;
24 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventType
;
25 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngTimestamp
;
26 import org
.eclipse
.linuxtools
.lttng
.jni
.JniEvent
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfEventParser
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfLocation
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
35 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> implements ITmfEventParser
<LttngEvent
> {
36 private LttngTimestamp eventTimestamp
= null;
37 private String eventSource
= null;
38 private LttngEventType eventType
= null;
39 private TextLttngEventContent eventContent
= null;
40 private String eventReference
= null;
42 private TextLttngEvent currentLttngEvent
= null;
44 private HashMap
<String
, LttngEventType
> traceTypes
= null;
46 private String tracepath
= ""; //$NON-NLS-1$
47 private FileReader fr
= null;
48 private BufferedReader br
= null;
49 private Long nbCharRead
= 0L;
51 private int cpuNumber
= -1;
53 private final boolean showDebug
= false;
55 public LTTngTextTrace(final IResource resource
, final String path
) throws Exception
{
56 this(resource
, path
, true); // false);
59 public LTTngTextTrace(final IResource resource
, final String path
, final boolean skipIndexing
) throws Exception
{
60 // super(null, LttngEvent.class, path, 1, !skipIndexing);
61 super(null, LttngEvent
.class, path
, 1000);
64 traceTypes
= new HashMap
<String
, LttngEventType
>();
66 eventTimestamp
= new LttngTimestamp();
67 eventSource
= "Kernel Core"; //$NON-NLS-1$
68 eventType
= new LttngEventType();
69 eventContent
= new TextLttngEventContent(currentLttngEvent
);
70 eventReference
= 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$
80 // Skip indexing if asked
81 // if ( skipIndexing == true ) {
82 // fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation<Long>(0L)));
83 ITmfContext context
= new TmfContext(new TmfLocation
<Long
>(0L), 0);
84 fIndexer
.updateIndex(context
, new LttngTimestamp(0L));
85 fParser
= (ITmfEventParser
) this;
91 final Long endTime
= currentLttngEvent
.getTimestamp().getValue();
92 positionToFirstEvent();
94 readNextEvent(new TmfContext(null, 0));
95 final Long starTime
= currentLttngEvent
.getTimestamp().getValue();
96 positionToFirstEvent();
98 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
99 new LttngTimestamp(endTime
)
105 public LTTngTextTrace(final LTTngTextTrace oldTrace
) throws Exception
{
106 this(oldTrace
.getResource(), oldTrace
.getPath(), true);
110 // fCheckpoints = oldTrace.fCheckpoints;
113 private boolean positionToFirstEvent() {
115 boolean isSuccessful
= true;
123 fr
= new FileReader(tracepath
);
124 br
= new BufferedReader(fr
);
126 // Skip the 2 lines header
130 // Make sure the event time is consistent
131 eventTimestamp
.setValue(0L);
133 catch (final IOException e
) {
134 isSuccessful
= false;
140 private void skipToPosition(final TmfLocation
<Long
> skip
) {
142 long skipPosition
= skip
.getLocation();
143 if ( skipPosition
< 0 )
146 if ( showDebug
== true ) {
147 System
.out
.println("skipToPosition(Long skipPosition)"); //$NON-NLS-1$
148 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
149 System
.out
.println();
151 positionToFirstEvent();
152 final long nbSkipped
= br
.skip(skipPosition
);
153 if ( nbSkipped
!= skipPosition
)
154 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); //$NON-NLS-1$
156 nbCharRead
= skipPosition
;
158 catch (final Exception e
) {
164 @SuppressWarnings("unchecked")
165 public TmfContext
seekEvent(ITmfLocation
<?
> location
) {
166 if (location
== null)
167 location
= new TmfLocation
<Long
>(0L);
169 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
))
170 skipToPosition((TmfLocation
<Long
>) location
);
172 final TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
174 return tmpTraceContext
;
178 public TmfContext
seekEvent(final double ratio
) {
179 // TODO Auto-generated method stub
184 public double getLocationRatio(final ITmfLocation
<?
> location
) {
185 // TODO Auto-generated method stub
189 private LttngEvent
parseMyNextEvent(final ITmfContext context
) {
191 // All parsing variables declared here so to be able to print them into the catch if needed
192 String tmpContent
= null;
194 int tmpPrevIndex
= 0;
196 String tracefile
= ""; //$NON-NLS-1$
198 String marker
= ""; //$NON-NLS-1$
201 long tmpNanosecond
= 0;
203 String parsedPayload
= ""; //$NON-NLS-1$
204 String markerName
= ""; //$NON-NLS-1$
205 Object payload
= ""; //$NON-NLS-1$
207 HashMap
<String
, LttngEventField
> fieldsMap
= null;
209 LttngEvent returnedEvent
= null;
212 tmpContent
= br
.readLine();
214 if (tmpContent
!= null) {
216 // -1 is the skip the end of line (\n)
217 nbCharRead
+= (tmpContent
.length()+1);
219 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getMapContent() != null) )
220 currentLttngEvent
.getContent().emptyContent();
222 // Tracefile and marker are first in the file
224 // kernel.syscall_entry:
225 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
228 // Evil exit case here : the two last line of the text dump does not contain "."
229 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
230 // Conclusion : this is ugly but fast.
231 if ( tmpCurIndex
< 0 ) {
232 if ( showDebug
== true ) {
233 System
.out
.println("END OF FILE."); //$NON-NLS-1$
234 System
.out
.println();
239 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
240 /*System.out.println(tracefile);*/
242 tmpPrevIndex
= tmpCurIndex
;
243 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
244 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
245 /*System.out.println(marker);*/
247 // Timestamp is next but is presented in second.milisecond format, we have to split them
250 tmpPrevIndex
= tmpCurIndex
+1;
251 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
252 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
253 /*System.out.println(tmpSecond);*/
255 tmpPrevIndex
= tmpCurIndex
+1;
256 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
257 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
258 /*System.out.println(tmpNanosecond);*/
260 // We have enough information here to set the timestamp
261 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
262 /*System.out.println(eventTimestamp.toString());*/
264 // Next field is the reference
265 // A long string enclosed by parenthesis and ending with a comma
266 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
267 tmpPrevIndex
= tmpCurIndex
+1;
268 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
269 tmpPrevIndex
= tmpCurIndex
+1;
270 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
271 final String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
272 /*System.out.println(fullTracePath);*/
274 final String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
275 /*System.out.println(traceName);*/
276 eventReference
= traceName
;
277 currentLttngEvent
.setReference(traceName
);
280 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
281 // They should be like the following :
282 // 4175, 4175, hal-acl-tool, , 4168,
285 tmpPrevIndex
= tmpCurIndex
+1;
286 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
288 tmpPrevIndex
= tmpCurIndex
+1;
289 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
291 tmpPrevIndex
= tmpCurIndex
+1;
292 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
294 tmpPrevIndex
= tmpCurIndex
+1;
295 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
297 tmpPrevIndex
= tmpCurIndex
+1;
298 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
300 tmpPrevIndex
= tmpCurIndex
+1;
301 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
303 // The next field is the CPU, in hexadecimal format
306 tmpPrevIndex
= tmpCurIndex
+1;
307 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
308 tmpPrevIndex
= tmpCurIndex
+2;
310 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
311 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
313 // Set the cpu number of trace if we found a "new" cpu
314 if ( cpuNumber
< (tmpCpu
+ 1) )
315 cpuNumber
= (int)(tmpCpu
+1);
318 // The last field is the parsed content
319 // It is enclosed by { }
321 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
323 // NOTE : it seems some state system events do not respect this format as they have no payload.
324 // We will create empty payload then.
325 final int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
326 if ( tmpIndex
!= -1 ) {
327 tmpPrevIndex
= tmpCurIndex
+1;
328 tmpCurIndex
= tmpIndex
;
329 tmpPrevIndex
= tmpCurIndex
+1;
330 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
331 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
333 // Now add each LttngField
334 boolean isDone
= false;
335 int tmpIndexBegin
= 0;
336 int tmpIndexEqual
= 0;
339 fieldsMap
= new HashMap
<String
, LttngEventField
>();
341 while ( isDone
== false ) {
342 tmpIndexEqual
= parsedPayload
.indexOf("=", tmpIndexBegin
); //$NON-NLS-1$
343 tmpIndexEnd
= parsedPayload
.indexOf(", ", tmpIndexEqual
); //$NON-NLS-1$
344 if ( tmpIndexEnd
== -1 ) {
345 tmpIndexEnd
= parsedPayload
.length();
349 markerName
= parsedPayload
.substring(tmpIndexBegin
, tmpIndexEqual
-1 ).trim();
350 payload
= parsedPayload
.substring(tmpIndexEqual
+1, tmpIndexEnd
).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
352 // Try to cast the payload into the correct type
354 payload
= Long
.parseLong((String
)payload
);
356 catch (final NumberFormatException e
) { }
358 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
359 fieldsMap
.put(markerName
, tmpField
);
361 tmpIndexBegin
= tmpIndexEnd
+1;
365 fieldsMap
= new HashMap
<String
, LttngEventField
>();
367 markerName
= ""; //$NON-NLS-1$
368 payload
= ""; //$NON-NLS-1$
370 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
371 fieldsMap
.put(markerName
, tmpField
);
374 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
376 // We now have what we need for the type
377 final String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
378 if ( traceTypes
.get(tmpTypeKey
) == null )
379 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
381 currentLttngEvent
.setContent(eventContent
);
382 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
384 returnedEvent
= currentLttngEvent
;
386 else if ( showDebug
== true ) {
387 System
.out
.println("NULL READING"); //$NON-NLS-1$
388 System
.out
.println();
389 returnedEvent
= null;
392 catch (final Exception e
) {
393 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
394 if ( tmpContent
!= null )
395 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
399 returnedEvent
= null;
402 return returnedEvent
;
406 public ITmfLocation
<?
> getCurrentLocation() {
407 return new TmfLocation
<Long
>(nbCharRead
);
411 public LttngEvent
parseEvent(ITmfContext context
) {
412 context
= seekEvent(context
.getLocation());
413 return parseMyNextEvent(context
);
417 public int getCpuNumber() {
424 // Redefine event to override method we know won't work with a Text tracefile
425 class TextLttngEvent
extends LttngEvent
{
427 public TextLttngEvent( final TmfTrace
<LttngEvent
> parent
,
428 final LttngTimestamp timestamp
,
430 final LttngEventType type
,
431 final LttngEventContent content
,
432 final String reference
)
434 super(parent
, timestamp
, source
, type
, content
, reference
, null);
437 @SuppressWarnings("unchecked")
438 public TextLttngEvent(final TextLttngEvent oldEvent
) {
440 (TmfTrace
<LttngEvent
>) oldEvent
.getTrace(),
441 (LttngTimestamp
)oldEvent
.getTimestamp(),
442 oldEvent
.getSource(),
444 oldEvent
.getContent(),
445 oldEvent
.getReference()
450 public JniEvent
convertEventTmfToJni() {
451 // System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
456 public void updateJniEventReference(final JniEvent newJniEventReference
) {
457 // System.out.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
462 class TextLttngEventContent
extends LttngEventContent
{
464 public TextLttngEventContent() {
468 public TextLttngEventContent(final TextLttngEvent thisParent
) {
469 super(thisParent
, null);
472 public TextLttngEventContent(final TextLttngEvent thisParent
, final HashMap
<String
, LttngEventField
> thisContent
) {
473 super(thisParent
, thisContent
);
476 public TextLttngEventContent(final TextLttngEventContent oldContent
) {
477 this(((TextLttngEvent
) oldContent
.getEvent()), oldContent
.getMapContent());
481 public LttngEventField
[] getFields() {
482 return getMapContent().values().toArray(new LttngEventField
[getMapContent().size()]);
486 public LttngEventField
getField(final String name
) {
487 final LttngEventField returnedField
= getMapContent().get(name
);
489 return returnedField
;
493 public LttngEventField
getField(final int position
) {
494 LttngEventField returnedField
= null;
497 label
= getEvent().getType().getFieldName(position
);
498 returnedField
= this.getField(label
);
500 // catch (TmfNoSuchFieldException e) {
501 // System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
504 return returnedField
;