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
.ITmfLocation
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfCheckpoint
;
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
> {
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
, 1);
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)));
88 final Long endTime
= currentLttngEvent
.getTimestamp().getValue();
89 positionToFirstEvent();
91 getNextEvent(new TmfContext(null, 0));
92 final Long starTime
= currentLttngEvent
.getTimestamp().getValue();
93 positionToFirstEvent();
95 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime
),
96 new LttngTimestamp(endTime
)
102 public LTTngTextTrace(final LTTngTextTrace oldTrace
) throws Exception
{
103 this(oldTrace
.getResource(), oldTrace
.getPath(), true);
107 fCheckpoints
= oldTrace
.fCheckpoints
;
110 private boolean positionToFirstEvent() {
112 boolean isSuccessful
= true;
120 fr
= new FileReader(tracepath
);
121 br
= new BufferedReader(fr
);
123 // Skip the 2 lines header
127 // Make sure the event time is consistent
128 eventTimestamp
.setValue(0L);
130 catch (final IOException e
) {
131 isSuccessful
= false;
137 private void skipToPosition(final TmfLocation
<Long
> skip
) {
139 long skipPosition
= skip
.getLocation();
140 if ( skipPosition
< 0 )
143 if ( showDebug
== true ) {
144 System
.out
.println("skipToPosition(Long skipPosition)"); //$NON-NLS-1$
145 System
.out
.println("\tSkipping to : " + skipPosition
); //$NON-NLS-1$
146 System
.out
.println();
148 positionToFirstEvent();
149 final long nbSkipped
= br
.skip(skipPosition
);
150 if ( nbSkipped
!= skipPosition
)
151 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); //$NON-NLS-1$
153 nbCharRead
= skipPosition
;
155 catch (final Exception e
) {
161 @SuppressWarnings("unchecked")
162 public TmfContext
seekLocation(ITmfLocation
<?
> location
) {
163 if (location
== null)
164 location
= new TmfLocation
<Long
>(0L);
166 if (!((TmfLocation
<Long
>) location
).getLocation().equals(nbCharRead
))
167 skipToPosition((TmfLocation
<Long
>) location
);
169 final TmfContext tmpTraceContext
= new TmfContext(location
, 0L);
171 return tmpTraceContext
;
175 public TmfContext
seekLocation(final double ratio
) {
176 // TODO Auto-generated method stub
181 public double getLocationRatio(final ITmfLocation
<?
> location
) {
182 // TODO Auto-generated method stub
186 private LttngEvent
parseMyNextEvent(final ITmfContext context
) {
188 // All parsing variables declared here so to be able to print them into the catch if needed
189 String tmpContent
= null;
191 int tmpPrevIndex
= 0;
193 String tracefile
= ""; //$NON-NLS-1$
195 String marker
= ""; //$NON-NLS-1$
198 long tmpNanosecond
= 0;
200 String parsedPayload
= ""; //$NON-NLS-1$
201 String markerName
= ""; //$NON-NLS-1$
202 Object payload
= ""; //$NON-NLS-1$
204 HashMap
<String
, LttngEventField
> fieldsMap
= null;
206 LttngEvent returnedEvent
= null;
209 tmpContent
= br
.readLine();
211 if (tmpContent
!= null) {
213 // -1 is the skip the end of line (\n)
214 nbCharRead
+= (tmpContent
.length()+1);
216 if ( (currentLttngEvent
!= null) && (currentLttngEvent
.getContent().getMapContent() != null) )
217 currentLttngEvent
.getContent().emptyContent();
219 // Tracefile and marker are first in the file
221 // kernel.syscall_entry:
222 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
225 // Evil exit case here : the two last line of the text dump does not contain "."
226 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
227 // Conclusion : this is ugly but fast.
228 if ( tmpCurIndex
< 0 ) {
229 if ( showDebug
== true ) {
230 System
.out
.println("END OF FILE."); //$NON-NLS-1$
231 System
.out
.println();
236 tracefile
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
237 /*System.out.println(tracefile);*/
239 tmpPrevIndex
= tmpCurIndex
;
240 tmpCurIndex
= tmpContent
.indexOf(":", tmpPrevIndex
); //$NON-NLS-1$
241 marker
= tmpContent
.substring(tmpPrevIndex
+1, tmpCurIndex
).trim();
242 /*System.out.println(marker);*/
244 // Timestamp is next but is presented in second.milisecond format, we have to split them
247 tmpPrevIndex
= tmpCurIndex
+1;
248 tmpCurIndex
= tmpContent
.indexOf(".", tmpPrevIndex
); //$NON-NLS-1$
249 tmpSecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
250 /*System.out.println(tmpSecond);*/
252 tmpPrevIndex
= tmpCurIndex
+1;
253 tmpCurIndex
= tmpContent
.indexOf(" ", tmpPrevIndex
); //$NON-NLS-1$
254 tmpNanosecond
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
255 /*System.out.println(tmpNanosecond);*/
257 // We have enough information here to set the timestamp
258 eventTimestamp
.setValue( (tmpSecond
* 1000000000) + tmpNanosecond
);
259 /*System.out.println(eventTimestamp.toString());*/
261 // Next field is the reference
262 // A long string enclosed by parenthesis and ending with a comma
263 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
264 tmpPrevIndex
= tmpCurIndex
+1;
265 tmpCurIndex
= tmpContent
.indexOf("(", tmpPrevIndex
); //$NON-NLS-1$
266 tmpPrevIndex
= tmpCurIndex
+1;
267 tmpCurIndex
= tmpContent
.indexOf("),", tmpPrevIndex
); //$NON-NLS-1$
268 final String fullTracePath
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
269 /*System.out.println(fullTracePath);*/
271 final String traceName
= fullTracePath
.substring(fullTracePath
.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
272 /*System.out.println(traceName);*/
273 eventReference
= traceName
;
274 currentLttngEvent
.setReference(traceName
);
277 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
278 // They should be like the following :
279 // 4175, 4175, hal-acl-tool, , 4168,
282 tmpPrevIndex
= tmpCurIndex
+1;
283 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
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 // The next field is the CPU, in hexadecimal format
303 tmpPrevIndex
= tmpCurIndex
+1;
304 tmpCurIndex
= tmpContent
.indexOf("0x", tmpPrevIndex
); //$NON-NLS-1$
305 tmpPrevIndex
= tmpCurIndex
+2;
307 tmpCurIndex
= tmpContent
.indexOf(",", tmpPrevIndex
); //$NON-NLS-1$
308 tmpCpu
= Long
.parseLong( tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim() );
310 // Set the cpu number of trace if we found a "new" cpu
311 if ( cpuNumber
< (tmpCpu
+ 1) )
312 cpuNumber
= (int)(tmpCpu
+1);
315 // The last field is the parsed content
316 // It is enclosed by { }
318 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
320 // NOTE : it seems some state system events do not respect this format as they have no payload.
321 // We will create empty payload then.
322 final int tmpIndex
= tmpContent
.indexOf("{", tmpPrevIndex
); //$NON-NLS-1$
323 if ( tmpIndex
!= -1 ) {
324 tmpPrevIndex
= tmpCurIndex
+1;
325 tmpCurIndex
= tmpIndex
;
326 tmpPrevIndex
= tmpCurIndex
+1;
327 tmpCurIndex
= tmpContent
.indexOf("}", tmpPrevIndex
); //$NON-NLS-1$
328 parsedPayload
= tmpContent
.substring(tmpPrevIndex
, tmpCurIndex
).trim();
330 // Now add each LttngField
331 boolean isDone
= false;
332 int tmpIndexBegin
= 0;
333 int tmpIndexEqual
= 0;
336 fieldsMap
= new HashMap
<String
, LttngEventField
>();
338 while ( isDone
== false ) {
339 tmpIndexEqual
= parsedPayload
.indexOf("=", tmpIndexBegin
); //$NON-NLS-1$
340 tmpIndexEnd
= parsedPayload
.indexOf(", ", tmpIndexEqual
); //$NON-NLS-1$
341 if ( tmpIndexEnd
== -1 ) {
342 tmpIndexEnd
= parsedPayload
.length();
346 markerName
= parsedPayload
.substring(tmpIndexBegin
, tmpIndexEqual
-1 ).trim();
347 payload
= parsedPayload
.substring(tmpIndexEqual
+1, tmpIndexEnd
).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
349 // Try to cast the payload into the correct type
351 payload
= Long
.parseLong((String
)payload
);
353 catch (final NumberFormatException e
) { }
355 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
356 fieldsMap
.put(markerName
, tmpField
);
358 tmpIndexBegin
= tmpIndexEnd
+1;
362 fieldsMap
= new HashMap
<String
, LttngEventField
>();
364 markerName
= ""; //$NON-NLS-1$
365 payload
= ""; //$NON-NLS-1$
367 final LttngEventField tmpField
= new LttngEventField(markerName
, payload
);
368 fieldsMap
.put(markerName
, tmpField
);
371 eventContent
= new TextLttngEventContent(currentLttngEvent
, fieldsMap
);
373 // We now have what we need for the type
374 final String tmpTypeKey
= tracefile
+ "/" + tmpCpu
+ "/" + marker
; //$NON-NLS-1$ //$NON-NLS-2$
375 if ( traceTypes
.get(tmpTypeKey
) == null )
376 traceTypes
.put(tmpTypeKey
, new LttngEventType(tracefile
, tmpCpu
, marker
, 0, fieldsMap
.keySet().toArray(new String
[fieldsMap
.size()] )) );
378 currentLttngEvent
.setContent(eventContent
);
379 currentLttngEvent
.setType(traceTypes
.get(tmpTypeKey
));
381 returnedEvent
= currentLttngEvent
;
383 else if ( showDebug
== true ) {
384 System
.out
.println("NULL READING"); //$NON-NLS-1$
385 System
.out
.println();
386 returnedEvent
= null;
389 catch (final Exception e
) {
390 System
.out
.println("Pos is :" + nbCharRead
); //$NON-NLS-1$
391 if ( tmpContent
!= null )
392 System
.out
.println("Erroneous content is :" + tmpContent
); //$NON-NLS-1$
396 returnedEvent
= null;
399 return returnedEvent
;
403 public ITmfLocation
<?
> getCurrentLocation() {
404 return new TmfLocation
<Long
>(nbCharRead
);
408 public LttngEvent
parseEvent(ITmfContext context
) {
409 context
= seekLocation(context
.getLocation());
410 return parseMyNextEvent(context
);
414 public int getCpuNumber() {
421 // Redefine event to override method we know won't work with a Text tracefile
422 class TextLttngEvent
extends LttngEvent
{
424 public TextLttngEvent( final TmfTrace
<LttngEvent
> parent
,
425 final LttngTimestamp timestamp
,
427 final LttngEventType type
,
428 final LttngEventContent content
,
429 final String reference
)
431 super(parent
, timestamp
, source
, type
, content
, reference
, null);
434 @SuppressWarnings("unchecked")
435 public TextLttngEvent(final TextLttngEvent oldEvent
) {
437 (TmfTrace
<LttngEvent
>) oldEvent
.getTrace(),
438 (LttngTimestamp
)oldEvent
.getTimestamp(),
439 oldEvent
.getSource(),
441 oldEvent
.getContent(),
442 oldEvent
.getReference()
447 public JniEvent
convertEventTmfToJni() {
448 // System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
453 public void updateJniEventReference(final JniEvent newJniEventReference
) {
454 // System.out.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
459 class TextLttngEventContent
extends LttngEventContent
{
461 public TextLttngEventContent() {
465 public TextLttngEventContent(final TextLttngEvent thisParent
) {
466 super(thisParent
, null);
469 public TextLttngEventContent(final TextLttngEvent thisParent
, final HashMap
<String
, LttngEventField
> thisContent
) {
470 super(thisParent
, thisContent
);
473 public TextLttngEventContent(final TextLttngEventContent oldContent
) {
474 this(((TextLttngEvent
) oldContent
.getEvent()), oldContent
.getMapContent());
478 public LttngEventField
[] getFields() {
479 return getMapContent().values().toArray(new LttngEventField
[getMapContent().size()]);
483 public LttngEventField
getField(final String name
) {
484 final LttngEventField returnedField
= getMapContent().get(name
);
486 return returnedField
;
490 public LttngEventField
getField(final int position
) {
491 LttngEventField returnedField
= null;
494 label
= getEvent().getType().getFieldName(position
);
495 returnedField
= this.getField(label
);
497 // catch (TmfNoSuchFieldException e) {
498 // System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
501 return returnedField
;