Fix for Bug338151
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng / src / org / eclipse / linuxtools / lttng / 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.lttng.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.linuxtools.lttng.event.LttngEvent;
21 import org.eclipse.linuxtools.lttng.event.LttngEventContent;
22 import org.eclipse.linuxtools.lttng.event.LttngEventField;
23 import org.eclipse.linuxtools.lttng.event.LttngEventReference;
24 import org.eclipse.linuxtools.lttng.event.LttngEventSource;
25 import org.eclipse.linuxtools.lttng.event.LttngEventType;
26 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
27 import org.eclipse.linuxtools.lttng.jni.JniEvent;
28 import org.eclipse.linuxtools.tmf.event.TmfNoSuchFieldException;
29 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
30 import org.eclipse.linuxtools.tmf.trace.ITmfLocation;
31 import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
32 import org.eclipse.linuxtools.tmf.trace.TmfCheckpoint;
33 import org.eclipse.linuxtools.tmf.trace.TmfContext;
34 import org.eclipse.linuxtools.tmf.trace.TmfLocation;
35 import org.eclipse.linuxtools.tmf.trace.TmfTrace;
36
37 public class LTTngTextTrace extends TmfTrace<LttngEvent> implements ITmfTrace {
38 private LttngTimestamp eventTimestamp = null;
39 private LttngEventSource eventSource = null;
40 private LttngEventType eventType = null;
41 private TextLttngEventContent eventContent = null;
42 private LttngEventReference eventReference = null;
43 // The actual event
44 private TextLttngEvent currentLttngEvent = null;
45
46 private HashMap<String, LttngEventType> traceTypes = null;
47
48 private String tracepath = ""; //$NON-NLS-1$
49 private FileReader fr = null;
50 private BufferedReader br = null;
51 private Long nbCharRead = 0L;
52
53 private int cpuNumber = -1;
54
55 private boolean showDebug = false;
56
57 public LTTngTextTrace(String path) throws Exception {
58 this(path, false);
59 }
60
61 public LTTngTextTrace(String path, boolean skipIndexing) throws Exception {
62 super(path, LttngEvent.class, path, 1, !skipIndexing);
63
64 tracepath = path;
65 traceTypes = new HashMap<String, LttngEventType>();
66
67 eventTimestamp = new LttngTimestamp();
68 eventSource = new LttngEventSource();
69 eventType = new LttngEventType();
70 eventContent = new TextLttngEventContent(currentLttngEvent);
71 eventReference = new LttngEventReference(this.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 }
79 else {
80 fIndexPageSize = 1000;
81
82 // Skip indexing if asked
83 // if ( skipIndexing == true ) {
84 fCheckpoints.add(new TmfCheckpoint(new LttngTimestamp(0L), new TmfLocation<Long>(0L)));
85 // }
86 // else {
87 // indexTrace(true);
88 // }
89
90 Long endTime = currentLttngEvent.getTimestamp().getValue();
91 positionToFirstEvent();
92
93 getNextEvent(new TmfContext(null, 0));
94 Long starTime = currentLttngEvent.getTimestamp().getValue();
95 positionToFirstEvent();
96
97 setTimeRange( new TmfTimeRange( new LttngTimestamp(starTime),
98 new LttngTimestamp(endTime)
99 ) );
100 }
101 }
102
103
104 public LTTngTextTrace(LTTngTextTrace oldTrace) throws Exception {
105 this(oldTrace.getPath(), true);
106
107 // *** VERIFY ***
108 // Is this safe?
109 fCheckpoints = oldTrace.fCheckpoints;
110 }
111
112 @Override
113 public LTTngTextTrace createTraceCopy() {
114
115 LTTngTextTrace returnedTrace = null;
116
117 try {
118 returnedTrace = new LTTngTextTrace(this);
119 }
120 catch (Exception e) {
121 System.out.println("ERROR : Could not create LTTngTextTrace copy (createTraceCopy).\nError is : " + e.getStackTrace()); //$NON-NLS-1$
122 }
123
124 return returnedTrace;
125 }
126
127 private boolean positionToFirstEvent() {
128
129 boolean isSuccessful = true;
130
131 try {
132 if ( br != null ) {
133 br.close();
134 fr.close();
135 }
136
137 fr = new FileReader(tracepath);
138 br = new BufferedReader(fr);
139
140 // Skip the 2 lines header
141 br.readLine();
142 br.readLine();
143
144 // Make sure the event time is consistent
145 eventTimestamp.setValue(0L);
146 }
147 catch (IOException e) {
148 isSuccessful = false;
149 }
150
151 return isSuccessful;
152 }
153
154 private void skipToPosition(TmfLocation<Long> skip) {
155 try {
156 long skipPosition = skip.getLocation();
157 if ( skipPosition < 0 ) {
158 skipPosition = 0L;
159 }
160
161 if ( showDebug == true ) {
162 System.out.println("skipToPosition(Long skipPosition)"); //$NON-NLS-1$
163 System.out.println("\tSkipping to : " + skipPosition); //$NON-NLS-1$
164 System.out.println();
165 }
166 positionToFirstEvent();
167 long nbSkipped = br.skip(skipPosition);
168 if ( nbSkipped != skipPosition) {
169 throw new IOException("Too few characters skipped, positionning failed! (skipToPosition)"); //$NON-NLS-1$
170 }
171
172 nbCharRead = skipPosition;
173 }
174 catch (Exception e) {
175 e.printStackTrace();
176 }
177 }
178
179 @Override
180 @SuppressWarnings("unchecked")
181 public TmfContext seekLocation(ITmfLocation<?> location) {
182 if (location == null) {
183 location = new TmfLocation<Long>(0L);
184 }
185
186 if (!((TmfLocation<Long>) location).getLocation().equals(nbCharRead)) {
187 skipToPosition((TmfLocation<Long>) location);
188 }
189
190 TmfContext tmpTraceContext = new TmfContext(location, 0L);
191
192 return tmpTraceContext;
193 }
194
195 @Override
196 public TmfContext seekLocation(double ratio) {
197 // TODO Auto-generated method stub
198 return null;
199 }
200
201 @Override
202 public double getLocationRatio(ITmfLocation<?> location) {
203 // TODO Auto-generated method stub
204 return 0;
205 }
206
207 private LttngEvent parseMyNextEvent(TmfContext context) {
208
209 // All parsing variables declared here so to be able to print them into the catch if needed
210 String tmpContent = null;
211 int tmpCurIndex = 0;
212 int tmpPrevIndex = 0;
213
214 String tracefile = ""; //$NON-NLS-1$
215 long tmpCpu = 0;
216 String marker = ""; //$NON-NLS-1$
217
218 long tmpSecond = 0;
219 long tmpNanosecond = 0;
220
221 String parsedPayload = ""; //$NON-NLS-1$
222 String markerName = ""; //$NON-NLS-1$
223 Object payload = ""; //$NON-NLS-1$
224
225 HashMap<String, LttngEventField> fieldsMap = null;
226
227 LttngEvent returnedEvent = null;
228
229 try {
230 tmpContent = br.readLine();
231
232 if (tmpContent != null) {
233 // *** NOTE :
234 // -1 is the skip the end of line (\n)
235 nbCharRead += (tmpContent.length()+1);
236
237 if ( (currentLttngEvent != null) && (currentLttngEvent.getContent().getRawContent() != null) ) {
238 currentLttngEvent.getContent().emptyContent();
239 }
240
241 // EventSource is always the same for now :
242 eventSource.setSourceId("Kernel Core"); //$NON-NLS-1$
243
244
245 // Tracefile and marker are first in the file
246 // Sound like :
247 // kernel.syscall_entry:
248 tmpCurIndex = tmpContent.indexOf(".", tmpPrevIndex); //$NON-NLS-1$
249
250 // *** HACK ***
251 // Evil exit case here : the two last line of the text dump does not contain "."
252 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
253 // Conclusion : this is ugly but fast.
254 if ( tmpCurIndex < 0 ) {
255 if ( showDebug == true ) {
256 System.out.println("END OF FILE."); //$NON-NLS-1$
257 System.out.println();
258 }
259 return null;
260 }
261
262 tracefile = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
263 /*System.out.println(tracefile);*/
264
265 tmpPrevIndex = tmpCurIndex;
266 tmpCurIndex = tmpContent.indexOf(":", tmpPrevIndex); //$NON-NLS-1$
267 marker = tmpContent.substring(tmpPrevIndex+1, tmpCurIndex ).trim();
268 /*System.out.println(marker);*/
269
270 // Timestamp is next but is presented in second.milisecond format, we have to split them
271 // Sound like :
272 // 952.162637168
273 tmpPrevIndex = tmpCurIndex+1;
274 tmpCurIndex = tmpContent.indexOf(".", tmpPrevIndex); //$NON-NLS-1$
275 tmpSecond = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
276 /*System.out.println(tmpSecond);*/
277
278 tmpPrevIndex = tmpCurIndex+1;
279 tmpCurIndex = tmpContent.indexOf(" ", tmpPrevIndex); //$NON-NLS-1$
280 tmpNanosecond = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
281 /*System.out.println(tmpNanosecond);*/
282
283 // We have enough information here to set the timestamp
284 eventTimestamp.setValue( (tmpSecond * 1000000000) + tmpNanosecond );
285 /*System.out.println(eventTimestamp.toString());*/
286
287 // Next field is the reference
288 // A long string enclosed by parenthesis and ending with a comma
289 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
290 tmpPrevIndex = tmpCurIndex+1;
291 tmpCurIndex = tmpContent.indexOf("(", tmpPrevIndex); //$NON-NLS-1$
292 tmpPrevIndex = tmpCurIndex+1;
293 tmpCurIndex = tmpContent.indexOf("),", tmpPrevIndex); //$NON-NLS-1$
294 String fullTracePath = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
295 /*System.out.println(fullTracePath);*/
296
297 eventReference.setValue(fullTracePath);
298 String traceName = fullTracePath.substring(fullTracePath.lastIndexOf("/")+1).trim(); //$NON-NLS-1$
299 /*System.out.println(traceName);*/
300 eventReference.setTracepath(traceName);
301
302
303 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
304 // They should be like the following :
305 // 4175, 4175, hal-acl-tool, , 4168,
306
307 // 1st comma
308 tmpPrevIndex = tmpCurIndex+1;
309 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
310 // 2nd comma
311 tmpPrevIndex = tmpCurIndex+1;
312 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
313 // 3rd comma
314 tmpPrevIndex = tmpCurIndex+1;
315 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
316 // 4th comma
317 tmpPrevIndex = tmpCurIndex+1;
318 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
319 // 5th comma
320 tmpPrevIndex = tmpCurIndex+1;
321 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
322 // 6th comma
323 tmpPrevIndex = tmpCurIndex+1;
324 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
325
326 // The next field is the CPU, in hexadecimal format
327 // Should be like :
328 // 0x0,
329 tmpPrevIndex = tmpCurIndex+1;
330 tmpCurIndex = tmpContent.indexOf("0x", tmpPrevIndex); //$NON-NLS-1$
331 tmpPrevIndex = tmpCurIndex+2;
332
333 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex); //$NON-NLS-1$
334 tmpCpu = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
335
336 // Set the cpu number of trace if we found a "new" cpu
337 if ( cpuNumber < (tmpCpu + 1) ) {
338 cpuNumber = (int)(tmpCpu+1);
339 }
340 /*System.out.println(tmpCpu);*/
341
342
343 // The last field is the parsed content
344 // It is enclosed by { }
345 // Look like :
346 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
347 //
348 // NOTE : it seems some state system events do not respect this format as they have no payload.
349 // We will create empty payload then.
350 int tmpIndex = tmpContent.indexOf("{", tmpPrevIndex); //$NON-NLS-1$
351 if ( tmpIndex != -1 ) {
352 tmpPrevIndex = tmpCurIndex+1;
353 tmpCurIndex = tmpIndex;
354 tmpPrevIndex = tmpCurIndex+1;
355 tmpCurIndex = tmpContent.indexOf("}", tmpPrevIndex); //$NON-NLS-1$
356 parsedPayload = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
357
358 // Now add each LttngField
359 boolean isDone = false;
360 int tmpIndexBegin = 0;
361 int tmpIndexEqual = 0;
362 int tmpIndexEnd = 0;
363
364 fieldsMap = new HashMap<String, LttngEventField>();
365
366 while ( isDone == false ) {
367 tmpIndexEqual = parsedPayload.indexOf("=", (int)tmpIndexBegin); //$NON-NLS-1$
368 tmpIndexEnd = parsedPayload.indexOf(", ", (int)tmpIndexEqual); //$NON-NLS-1$
369 if ( tmpIndexEnd == -1 ) {
370 tmpIndexEnd = parsedPayload.length();
371 isDone = true;
372 }
373
374 markerName = parsedPayload.substring((int)tmpIndexBegin, (int)tmpIndexEqual-1 ).trim();
375 payload = ((String)parsedPayload.substring((int)tmpIndexEqual+1, (int)tmpIndexEnd )).replace("\"", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
376
377 // Try to cast the payload into the correct type
378 try {
379 payload = Long.parseLong((String)payload);
380 }
381 catch (NumberFormatException e) { }
382
383 LttngEventField tmpField = new LttngEventField(eventContent, markerName, payload);
384 fieldsMap.put(markerName, tmpField);
385
386 tmpIndexBegin = tmpIndexEnd+1;
387 }
388 }
389 else {
390 fieldsMap = new HashMap<String, LttngEventField>();
391
392 markerName = ""; //$NON-NLS-1$
393 payload = ""; //$NON-NLS-1$
394
395 LttngEventField tmpField = new LttngEventField(eventContent, markerName, payload);
396 fieldsMap.put(markerName, tmpField);
397 }
398
399 eventContent = new TextLttngEventContent(currentLttngEvent, fieldsMap);
400
401 // We now have what we need for the type
402 String tmpTypeKey = tracefile + "/" + tmpCpu + "/" + marker; //$NON-NLS-1$ //$NON-NLS-2$
403 if ( traceTypes.get(tmpTypeKey) == null ) {
404 traceTypes.put(tmpTypeKey, new LttngEventType(tracefile, tmpCpu, marker, 0, fieldsMap.keySet().toArray(new String[fieldsMap.size()] )) );
405 }
406
407 currentLttngEvent.setContent(eventContent);
408 currentLttngEvent.setType(traceTypes.get(tmpTypeKey));
409
410 returnedEvent = currentLttngEvent;
411 }
412 else if ( showDebug == true ) {
413 System.out.println("NULL READING"); //$NON-NLS-1$
414 System.out.println();
415 returnedEvent = null;
416 }
417 }
418 catch (Exception e) {
419 System.out.println("Pos is :" + nbCharRead); //$NON-NLS-1$
420 if ( tmpContent != null ) {
421 System.out.println("Erroneous content is :" + tmpContent); //$NON-NLS-1$
422 }
423
424 tmpContent = null;
425 e.printStackTrace();
426 returnedEvent = null;
427 }
428
429 return returnedEvent;
430 }
431
432 @Override
433 public ITmfLocation<?> getCurrentLocation() {
434 return new TmfLocation<Long>(nbCharRead);
435 }
436
437 @Override
438 public LttngEvent parseEvent(TmfContext context) {
439 context = seekLocation(context.getLocation());
440 return parseMyNextEvent(context);
441
442 }
443
444 public int getCpuNumber() {
445 return cpuNumber;
446 }
447
448 }
449
450
451 // Redefine event to override method we know won't work with a Text tracefile
452 class TextLttngEvent extends LttngEvent {
453
454 public TextLttngEvent( TmfTrace<LttngEvent> parent,
455 LttngTimestamp timestamp,
456 LttngEventSource source,
457 LttngEventType type,
458 LttngEventContent content,
459 LttngEventReference reference)
460 {
461 super(parent, timestamp, source, type, content, reference, null);
462 }
463
464 public TextLttngEvent(TextLttngEvent oldEvent) {
465 this(
466 oldEvent.getParentTrace(),
467 (LttngTimestamp)oldEvent.getTimestamp(),
468 (LttngEventSource)oldEvent.getSource(),
469 (LttngEventType)oldEvent.getType(),
470 (LttngEventContent)oldEvent.getContent(),
471 (LttngEventReference)oldEvent.getReference()
472 );
473 }
474
475 @Override
476 public JniEvent convertEventTmfToJni() {
477 System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format."); //$NON-NLS-1$
478 return null;
479 }
480
481 @Override
482 public void updateJniEventReference(JniEvent newJniEventReference) {
483 System.out.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null."); //$NON-NLS-1$
484 }
485 }
486
487
488 class TextLttngEventContent extends LttngEventContent {
489
490 public TextLttngEventContent() {
491 super();
492 }
493
494 public TextLttngEventContent(TextLttngEvent thisParent) {
495 super(thisParent, null);
496 }
497
498 public TextLttngEventContent(TextLttngEvent thisParent, HashMap<String, LttngEventField> thisContent) {
499 super(thisParent, thisContent);
500 }
501
502 public TextLttngEventContent(TextLttngEventContent oldContent) {
503 this( (TextLttngEvent)oldContent.fParentEvent, oldContent.getRawContent());
504 }
505
506 @Override
507 public LttngEventField[] getFields() {
508 return getRawContent().values().toArray(new LttngEventField[getRawContent().size()]);
509 }
510
511 @Override
512 public LttngEventField getField(String name) {
513 LttngEventField returnedField = getRawContent().get(name);
514
515 return returnedField;
516 }
517
518 @Override
519 public LttngEventField getField(int position) {
520 LttngEventField returnedField = null;
521 String label = null;
522 try {
523 label = fParentEvent.getType().getLabel(position);
524 returnedField = this.getField(label);
525 }
526 catch (TmfNoSuchFieldException e) {
527 System.out.println("Invalid field position requested : " + position + ", ignoring (getField)."); //$NON-NLS-1$ //$NON-NLS-2$
528 }
529
530 return returnedField;
531 }
532 }
This page took 0.043827 seconds and 5 git commands to generate.