Merge branch 'master'
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.core / src / org / eclipse / linuxtools / internal / lttng / core / trace / LTTngTextTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
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
8 *
9 * Contributors:
10 * William Bourque (wbourque@gmail.com) - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.lttng.core.trace;
14
15 import java.io.BufferedReader;
16 import java.io.FileReader;
17 import java.io.IOException;
18 import java.util.HashMap;
19
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;
35
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;
42 // The actual event
43 private TextLttngEvent currentLttngEvent = null;
44
45 private HashMap<String, LttngEventType> traceTypes = null;
46
47 private String tracepath = ""; //$NON-NLS-1$
48 private FileReader fr = null;
49 private BufferedReader br = null;
50 private Long nbCharRead = 0L;
51
52 private int cpuNumber = -1;
53
54 private final boolean showDebug = false;
55
56 public LTTngTextTrace(final IResource resource, final String path) throws Exception {
57 this(resource, path, true); // false);
58 }
59
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);
63
64 tracepath = path;
65 traceTypes = new HashMap<String, LttngEventType>();
66
67 eventTimestamp = new LttngTimestamp();
68 eventSource = "Kernel Core"; //$NON-NLS-1$
69 eventType = new LttngEventType();
70 eventContent = new TextLttngEventContent(currentLttngEvent);
71 eventReference = getName();
72
73 currentLttngEvent = new TextLttngEvent(this, eventTimestamp, eventSource, eventType, eventContent, eventReference);
74 eventContent.setEvent(currentLttngEvent);
75
76 if ( positionToFirstEvent() == false )
77 throw new IOException("Fail to position to the beginning of the trace"); //$NON-NLS-1$
78 else {
79 setCacheSize(1000);
80 ITmfContext context = new TmfContext(new TmfLocation<Long>(0L), 0);
81 getIndexer().updateIndex(context, new LttngTimestamp(0L));
82 setParser((ITmfEventParser<LttngEvent>) this);
83
84 final Long endTime = currentLttngEvent.getTimestamp().getValue();
85 positionToFirstEvent();
86
87 getNext(new TmfContext(null, 0));
88 final Long starTime = currentLttngEvent.getTimestamp().getValue();
89 positionToFirstEvent();
90
91 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime),
92 new LttngTimestamp(endTime)
93 ) );
94 }
95 }
96
97
98 public LTTngTextTrace(final LTTngTextTrace oldTrace) throws Exception {
99 this(oldTrace.getResource(), oldTrace.getPath(), true);
100
101 // *** VERIFY ***
102 // Is this safe?
103 // fCheckpoints = oldTrace.fCheckpoints;
104 }
105
106 private boolean positionToFirstEvent() {
107
108 boolean isSuccessful = true;
109
110 try {
111 if ( br != null ) {
112 br.close();
113 fr.close();
114 }
115
116 fr = new FileReader(tracepath);
117 br = new BufferedReader(fr);
118
119 // Skip the 2 lines header
120 br.readLine();
121 br.readLine();
122
123 // Make sure the event time is consistent
124 eventTimestamp.setValue(0L);
125 }
126 catch (final IOException e) {
127 isSuccessful = false;
128 }
129
130 return isSuccessful;
131 }
132
133 private void skipToPosition(final TmfLocation<Long> skip) {
134 try {
135 long skipPosition = skip.getLocation();
136 if ( skipPosition < 0 )
137 skipPosition = 0L;
138
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();
143 }
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$
148
149 nbCharRead = skipPosition;
150 }
151 catch (final Exception e) {
152 e.printStackTrace();
153 }
154 }
155
156 @Override
157 @SuppressWarnings("unchecked")
158 public TmfContext seekEvent(ITmfLocation<?> location) {
159 if (location == null)
160 location = new TmfLocation<Long>(0L);
161
162 if (!((TmfLocation<Long>) location).getLocation().equals(nbCharRead))
163 skipToPosition((TmfLocation<Long>) location);
164
165 final TmfContext tmpTraceContext = new TmfContext(location, 0L);
166
167 return tmpTraceContext;
168 }
169
170 @Override
171 public TmfContext seekEvent(final double ratio) {
172 // TODO Auto-generated method stub
173 return null;
174 }
175
176 @Override
177 public double getLocationRatio(final ITmfLocation<?> location) {
178 // TODO Auto-generated method stub
179 return 0;
180 }
181
182 private LttngEvent parseMyNextEvent(final ITmfContext context) {
183
184 // All parsing variables declared here so to be able to print them into the catch if needed
185 String tmpContent = null;
186 int tmpCurIndex = 0;
187 int tmpPrevIndex = 0;
188
189 String tracefile = ""; //$NON-NLS-1$
190 long tmpCpu = 0;
191 String marker = ""; //$NON-NLS-1$
192
193 long tmpSecond = 0;
194 long tmpNanosecond = 0;
195
196 String parsedPayload = ""; //$NON-NLS-1$
197 String markerName = ""; //$NON-NLS-1$
198 Object payload = ""; //$NON-NLS-1$
199
200 HashMap<String, LttngEventField> fieldsMap = null;
201
202 LttngEvent returnedEvent = null;
203
204 try {
205 tmpContent = br.readLine();
206
207 if (tmpContent != null) {
208 // *** NOTE :
209 // -1 is the skip the end of line (\n)
210 nbCharRead += (tmpContent.length()+1);
211
212 if ( (currentLttngEvent != null) && (currentLttngEvent.getContent().getMapContent() != null) )
213 currentLttngEvent.getContent().emptyContent();
214
215 // Tracefile and marker are first in the file
216 // Sound like :
217 // kernel.syscall_entry:
218 tmpCurIndex = tmpContent.indexOf(".", tmpPrevIndex); //$NON-NLS-1$
219
220 // *** HACK ***
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();
228 }
229 return null;
230 }
231
232 tracefile = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
233 /*System.out.println(tracefile);*/
234
235 tmpPrevIndex = tmpCurIndex;
236 tmpCurIndex = tmpContent.indexOf(":", tmpPrevIndex); //$NON-NLS-1$
237 marker = tmpContent.substring(tmpPrevIndex+1, tmpCurIndex ).trim();
238 /*System.out.println(marker);*/
239
240 // Timestamp is next but is presented in second.milisecond format, we have to split them
241 // Sound like :
242 // 952.162637168
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);*/
247
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);*/
252
253 // We have enough information here to set the timestamp
254 eventTimestamp.setValue( (tmpSecond * 1000000000) + tmpNanosecond );
255 /*System.out.println(eventTimestamp.toString());*/
256
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);*/
266
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);
271
272
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,
276
277 // 1st comma
278 tmpPrevIndex = tmpCurIndex+1;
279 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
280 // 2nd comma
281 tmpPrevIndex = tmpCurIndex+1;
282 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
283 // 3rd comma
284 tmpPrevIndex = tmpCurIndex+1;
285 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
286 // 4th comma
287 tmpPrevIndex = tmpCurIndex+1;
288 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
289 // 5th comma
290 tmpPrevIndex = tmpCurIndex+1;
291 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
292 // 6th comma
293 tmpPrevIndex = tmpCurIndex+1;
294 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
295
296 // The next field is the CPU, in hexadecimal format
297 // Should be like :
298 // 0x0,
299 tmpPrevIndex = tmpCurIndex+1;
300 tmpCurIndex = tmpContent.indexOf("0x", tmpPrevIndex); //$NON-NLS-1$
301 tmpPrevIndex = tmpCurIndex+2;
302
303 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
304 tmpCpu = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
305
306 // Set the cpu number of trace if we found a "new" cpu
307 if ( cpuNumber < (tmpCpu + 1) )
308 cpuNumber = (int)(tmpCpu+1);
309
310
311 // The last field is the parsed content
312 // It is enclosed by { }
313 // Look like :
314 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
315 //
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();
325
326 // Now add each LttngField
327 boolean isDone = false;
328 int tmpIndexBegin = 0;
329 int tmpIndexEqual = 0;
330 int tmpIndexEnd = 0;
331
332 fieldsMap = new HashMap<String, LttngEventField>();
333
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();
339 isDone = true;
340 }
341
342 markerName = parsedPayload.substring(tmpIndexBegin, tmpIndexEqual-1 ).trim();
343 payload = parsedPayload.substring(tmpIndexEqual+1, tmpIndexEnd ).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
344
345 // Try to cast the payload into the correct type
346 try {
347 payload = Long.parseLong((String)payload);
348 }
349 catch (final NumberFormatException e) { }
350
351 final LttngEventField tmpField = new LttngEventField(markerName, payload);
352 fieldsMap.put(markerName, tmpField);
353
354 tmpIndexBegin = tmpIndexEnd+1;
355 }
356 }
357 else {
358 fieldsMap = new HashMap<String, LttngEventField>();
359
360 markerName = ""; //$NON-NLS-1$
361 payload = ""; //$NON-NLS-1$
362
363 final LttngEventField tmpField = new LttngEventField(markerName, payload);
364 fieldsMap.put(markerName, tmpField);
365 }
366
367 eventContent = new TextLttngEventContent(currentLttngEvent, fieldsMap);
368
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()] )) );
373
374 currentLttngEvent.setContent(eventContent);
375 currentLttngEvent.setType(traceTypes.get(tmpTypeKey));
376
377 returnedEvent = currentLttngEvent;
378 }
379 else if ( showDebug == true ) {
380 System.out.println("NULL READING"); //$NON-NLS-1$
381 System.out.println();
382 returnedEvent = null;
383 }
384 }
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$
389
390 tmpContent = null;
391 e.printStackTrace();
392 returnedEvent = null;
393 }
394
395 return returnedEvent;
396 }
397
398 @Override
399 public ITmfLocation<?> getCurrentLocation() {
400 return new TmfLocation<Long>(nbCharRead);
401 }
402
403 @Override
404 public LttngEvent parseEvent(ITmfContext context) {
405 context = seekEvent(context.getLocation());
406 return parseMyNextEvent(context);
407
408 }
409
410 public int getCpuNumber() {
411 return cpuNumber;
412 }
413
414 /* (non-Javadoc)
415 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)
416 */
417 @Override
418 public boolean validate(IProject project, String path) {
419 return fileExists(path);
420 }
421
422 }
423
424
425 // Redefine event to override method we know won't work with a Text tracefile
426 class TextLttngEvent extends LttngEvent {
427
428 public TextLttngEvent( final TmfTrace<LttngEvent> parent,
429 final LttngTimestamp timestamp,
430 final String source,
431 final LttngEventType type,
432 final LttngEventContent content,
433 final String reference)
434 {
435 super(parent, timestamp, source, type, content, reference, null);
436 }
437
438 @SuppressWarnings("unchecked")
439 public TextLttngEvent(final TextLttngEvent oldEvent) {
440 this(
441 (TmfTrace<LttngEvent>) oldEvent.getTrace(),
442 (LttngTimestamp)oldEvent.getTimestamp(),
443 oldEvent.getSource(),
444 oldEvent.getType(),
445 oldEvent.getContent(),
446 oldEvent.getReference()
447 );
448 }
449
450 @Override
451 public JniEvent convertEventTmfToJni() {
452 // System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
453 return null;
454 }
455
456 @Override
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$
459 }
460 }
461
462
463 class TextLttngEventContent extends LttngEventContent {
464
465 public TextLttngEventContent() {
466 super();
467 }
468
469 public TextLttngEventContent(final TextLttngEvent thisParent) {
470 super(thisParent, null);
471 }
472
473 public TextLttngEventContent(final TextLttngEvent thisParent, final HashMap<String, LttngEventField> thisContent) {
474 super(thisParent, thisContent);
475 }
476
477 public TextLttngEventContent(final TextLttngEventContent oldContent) {
478 this(((TextLttngEvent) oldContent.getEvent()), oldContent.getMapContent());
479 }
480
481 @Override
482 public LttngEventField[] getFields() {
483 return getMapContent().values().toArray(new LttngEventField[getMapContent().size()]);
484 }
485
486 @Override
487 public LttngEventField getField(final String name) {
488 final LttngEventField returnedField = getMapContent().get(name);
489
490 return returnedField;
491 }
492
493 @Override
494 public LttngEventField getField(final int position) {
495 LttngEventField returnedField = null;
496 String label = null;
497 // try {
498 label = getEvent().getType().getFieldName(position);
499 returnedField = this.getField(label);
500 // }
501 // catch (TmfNoSuchFieldException e) {
502 // System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
503 // }
504
505 return returnedField;
506 }
507 }
This page took 0.044826 seconds and 6 git commands to generate.