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
.IProject
;
21 import org
.eclipse
.core
.resources
.IResource
;
22 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEvent
;
23 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventContent
;
24 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventField
;
25 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngEventType
;
26 import org
.eclipse
.linuxtools
.internal
.lttng
.core
.event
.LttngTimestamp
;
27 import org
.eclipse
.linuxtools
.lttng
.jni
.JniEvent
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfEventParser
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfLocation
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
36 public class LTTngTextTrace
extends TmfTrace
<LttngEvent
> implements ITmfEventParser
<LttngEvent
> {
37 private LttngTimestamp eventTimestamp
= null;
38 private String eventSource
= null;
39 private LttngEventType eventType
= null;
40 private TextLttngEventContent eventContent
= null;
41 private String 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 final boolean showDebug
= false;
56 public LTTngTextTrace(final IResource resource
, final String path
) throws Exception
{
57 this(resource
, path
, true); // false);
60 public LTTngTextTrace(final IResource resource
, final String path
, final boolean skipIndexing
) throws Exception
{
61 // super(null, LttngEvent.class, path, 1, !skipIndexing);
62 super(null, LttngEvent
.class, path
, 1000);
65 traceTypes
= new HashMap
<String
, LttngEventType
>();
67 eventTimestamp
= new LttngTimestamp();
68 eventSource
= "Kernel Core"; //$NON-NLS-1$
69 eventType
= new LttngEventType();
70 eventContent
= new TextLttngEventContent(currentLttngEvent
);
71 eventReference
= 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 ITmfContext context
= new TmfContext(new TmfLocation
<Long
>(0L), 0);
81 getIndexer().updateIndex(context
, new LttngTimestamp(0L));
82 setParser((ITmfEventParser
<LttngEvent
>) this);
84 final Long endTime
= currentLttngEvent
.getTimestamp().getValue();
85 positionToFirstEvent();
87 getNext(new TmfContext(null, 0));
88 final Long starTime
= currentLttngEvent
.getTimestamp().getValue();
89 positionToFirstEvent();
91 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
92 new LttngTimestamp(endTime
)
98 public LTTngTextTrace(final LTTngTextTrace oldTrace
) throws Exception
{
99 this(oldTrace
.getResource(), oldTrace
.getPath(), true);
103 // fCheckpoints = oldTrace.fCheckpoints;
106 private boolean positionToFirstEvent() {
108 boolean isSuccessful
= true;
116 fr
= new FileReader(tracepath
);
117 br
= new BufferedReader(fr
);
119 // Skip the 2 lines header
123 // Make sure the event time is consistent
124 eventTimestamp
.setValue(0L);
126 catch (final IOException e
) {
127 isSuccessful
= false;
133 private void skipToPosition(final TmfLocation
<Long
> skip
) {
135 long skipPosition
= skip
.getLocation();
136 if ( skipPosition
< 0 )
139 if ( showDebug
== true ) {
140 System
.out
.println("skipToPosition(Long skipPosition)"); //$NON-NLS-1$
141 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
142 System
.out
.println();
144 positionToFirstEvent();
145 final long nbSkipped
= br
.skip(skipPosition
);
146 if ( nbSkipped
!= skipPosition
)
147 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); //$NON-NLS-1$
149 nbCharRead
= skipPosition
;
151 catch (final Exception e
) {
157 @SuppressWarnings("unchecked")
158 public TmfContext
seekEvent(ITmfLocation
<?
> location
) {
159 if (location
== null)
160 location
= new TmfLocation
<Long
>(0L);
162 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
))
163 skipToPosition((TmfLocation
<Long
>) location
);
165 final TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
167 return tmpTraceContext
;
171 public TmfContext
seekEvent(final double ratio
) {
172 // TODO Auto-generated method stub
177 public double getLocationRatio(final ITmfLocation
<?
> location
) {
178 // TODO Auto-generated method stub
182 private LttngEvent
parseMyNextEvent(final ITmfContext context
) {
184 // All parsing variables declared here so to be able to print them into the catch if needed
185 String tmpContent
= null;
187 int tmpPrevIndex
= 0;
189 String tracefile
= ""; //$NON-NLS-1$
191 String marker
= ""; //$NON-NLS-1$
194 long tmpNanosecond
= 0;
196 String parsedPayload
= ""; //$NON-NLS-1$
197 String markerName
= ""; //$NON-NLS-1$
198 Object payload
= ""; //$NON-NLS-1$
200 HashMap
<String
, LttngEventField
> fieldsMap
= null;
202 LttngEvent returnedEvent
= null;
205 tmpContent
= br
.readLine();
207 if (tmpContent
!= null) {
209 // -1 is the skip the end of line (\n)
210 nbCharRead
+= (tmpContent
.length()+1);
212 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getMapContent() != null) )
213 currentLttngEvent
.getContent().emptyContent();
215 // Tracefile and marker are first in the file
217 // kernel.syscall_entry:
218 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
221 // Evil exit case here : the two last line of the text dump does not contain "."
222 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
223 // Conclusion : this is ugly but fast.
224 if ( tmpCurIndex
< 0 ) {
225 if ( showDebug
== true ) {
226 System
.out
.println("END OF FILE."); //$NON-NLS-1$
227 System
.out
.println();
232 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
233 /*System.out.println(tracefile);*/
235 tmpPrevIndex
= tmpCurIndex
;
236 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
237 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
238 /*System.out.println(marker);*/
240 // Timestamp is next but is presented in second.milisecond format, we have to split them
243 tmpPrevIndex
= tmpCurIndex
+1;
244 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
245 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
246 /*System.out.println(tmpSecond);*/
248 tmpPrevIndex
= tmpCurIndex
+1;
249 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
250 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
251 /*System.out.println(tmpNanosecond);*/
253 // We have enough information here to set the timestamp
254 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
255 /*System.out.println(eventTimestamp.toString());*/
257 // Next field is the reference
258 // A long string enclosed by parenthesis and ending with a comma
259 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
260 tmpPrevIndex
= tmpCurIndex
+1;
261 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
262 tmpPrevIndex
= tmpCurIndex
+1;
263 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
264 final String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
265 /*System.out.println(fullTracePath);*/
267 final String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
268 /*System.out.println(traceName);*/
269 eventReference
= traceName
;
270 currentLttngEvent
.setReference(traceName
);
273 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
274 // They should be like the following :
275 // 4175, 4175, hal-acl-tool, , 4168,
278 tmpPrevIndex
= tmpCurIndex
+1;
279 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
281 tmpPrevIndex
= tmpCurIndex
+1;
282 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
284 tmpPrevIndex
= tmpCurIndex
+1;
285 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
287 tmpPrevIndex
= tmpCurIndex
+1;
288 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
290 tmpPrevIndex
= tmpCurIndex
+1;
291 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
293 tmpPrevIndex
= tmpCurIndex
+1;
294 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
296 // The next field is the CPU, in hexadecimal format
299 tmpPrevIndex
= tmpCurIndex
+1;
300 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
301 tmpPrevIndex
= tmpCurIndex
+2;
303 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
304 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
306 // Set the cpu number of trace if we found a "new" cpu
307 if ( cpuNumber
< (tmpCpu
+ 1) )
308 cpuNumber
= (int)(tmpCpu
+1);
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 final int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
319 if ( tmpIndex
!= -1 ) {
320 tmpPrevIndex
= tmpCurIndex
+1;
321 tmpCurIndex
= tmpIndex
;
322 tmpPrevIndex
= tmpCurIndex
+1;
323 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
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("=", tmpIndexBegin
); //$NON-NLS-1$
336 tmpIndexEnd
= parsedPayload
.indexOf(", ", tmpIndexEqual
); //$NON-NLS-1$
337 if ( tmpIndexEnd
== -1 ) {
338 tmpIndexEnd
= parsedPayload
.length();
342 markerName
= parsedPayload
.substring(tmpIndexBegin
, tmpIndexEqual
-1 ).trim();
343 payload
= parsedPayload
.substring(tmpIndexEqual
+1, tmpIndexEnd
).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
345 // Try to cast the payload into the correct type
347 payload
= Long
.parseLong((String
)payload
);
349 catch (final NumberFormatException e
) { }
351 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
352 fieldsMap
.put(markerName
, tmpField
);
354 tmpIndexBegin
= tmpIndexEnd
+1;
358 fieldsMap
= new HashMap
<String
, LttngEventField
>();
360 markerName
= ""; //$NON-NLS-1$
361 payload
= ""; //$NON-NLS-1$
363 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
364 fieldsMap
.put(markerName
, tmpField
);
367 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
369 // We now have what we need for the type
370 final String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
371 if ( traceTypes
.get(tmpTypeKey
) == null )
372 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
374 currentLttngEvent
.setContent(eventContent
);
375 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
377 returnedEvent
= currentLttngEvent
;
379 else if ( showDebug
== true ) {
380 System
.out
.println("NULL READING"); //$NON-NLS-1$
381 System
.out
.println();
382 returnedEvent
= null;
385 catch (final Exception e
) {
386 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
387 if ( tmpContent
!= null )
388 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
392 returnedEvent
= null;
395 return returnedEvent
;
399 public ITmfLocation
<?
> getCurrentLocation() {
400 return new TmfLocation
<Long
>(nbCharRead
);
404 public LttngEvent
parseEvent(ITmfContext context
) {
405 context
= seekEvent(context
.getLocation());
406 return parseMyNextEvent(context
);
410 public int getCpuNumber() {
415 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)
418 public boolean validate(IProject project
, String path
) {
419 return fileExists(path
);
425 // Redefine event to override method we know won't work with a Text tracefile
426 class TextLttngEvent
extends LttngEvent
{
428 public TextLttngEvent( final TmfTrace
<LttngEvent
> parent
,
429 final LttngTimestamp timestamp
,
431 final LttngEventType type
,
432 final LttngEventContent content
,
433 final String reference
)
435 super(parent
, timestamp
, source
, type
, content
, reference
, null);
438 @SuppressWarnings("unchecked")
439 public TextLttngEvent(final TextLttngEvent oldEvent
) {
441 (TmfTrace
<LttngEvent
>) oldEvent
.getTrace(),
442 (LttngTimestamp
)oldEvent
.getTimestamp(),
443 oldEvent
.getSource(),
445 oldEvent
.getContent(),
446 oldEvent
.getReference()
451 public JniEvent
convertEventTmfToJni() {
452 // System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
457 public void updateJniEventReference(final JniEvent newJniEventReference
) {
458 // System.out.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
463 class TextLttngEventContent
extends LttngEventContent
{
465 public TextLttngEventContent() {
469 public TextLttngEventContent(final TextLttngEvent thisParent
) {
470 super(thisParent
, null);
473 public TextLttngEventContent(final TextLttngEvent thisParent
, final HashMap
<String
, LttngEventField
> thisContent
) {
474 super(thisParent
, thisContent
);
477 public TextLttngEventContent(final TextLttngEventContent oldContent
) {
478 this(((TextLttngEvent
) oldContent
.getEvent()), oldContent
.getMapContent());
482 public LttngEventField
[] getFields() {
483 return getMapContent().values().toArray(new LttngEventField
[getMapContent().size()]);
487 public LttngEventField
getField(final String name
) {
488 final LttngEventField returnedField
= getMapContent().get(name
);
490 return returnedField
;
494 public LttngEventField
getField(final int position
) {
495 LttngEventField returnedField
= null;
498 label
= getEvent().getType().getFieldName(position
);
499 returnedField
= this.getField(label
);
501 // catch (TmfNoSuchFieldException e) {
502 // System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
505 return returnedField
;