2010-10-26 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug309042
[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 = "";
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);
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");
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());
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)");
163 System.out.println("\tSkipping to : " + skipPosition);
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)");
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 private LttngEvent parseMyNextEvent(TmfContext context) {
196
197 // All parsing variables declared here so to be able to print them into the catch if needed
198 String tmpContent = null;
199 int tmpCurIndex = 0;
200 int tmpPrevIndex = 0;
201
202 String tracefile = "";
203 long tmpCpu = 0;
204 String marker = "";
205
206 long tmpSecond = 0;
207 long tmpNanosecond = 0;
208
209 String parsedPayload = "";
210 String markerName = "";
211 Object payload = "";
212
213 HashMap<String, LttngEventField> fieldsMap = null;
214
215 LttngEvent returnedEvent = null;
216
217 try {
218 tmpContent = br.readLine();
219
220 if (tmpContent != null) {
221 // *** NOTE :
222 // -1 is the skip the end of line (\n)
223 nbCharRead += (tmpContent.length()+1);
224
225 if ( (currentLttngEvent != null) && (currentLttngEvent.getContent().getRawContent() != null) ) {
226 currentLttngEvent.getContent().emptyContent();
227 }
228
229 // EventSource is always the same for now :
230 eventSource.setSourceId("Kernel Core");
231
232
233 // Tracefile and marker are first in the file
234 // Sound like :
235 // kernel.syscall_entry:
236 tmpCurIndex = tmpContent.indexOf(".", tmpPrevIndex);
237
238 // *** HACK ***
239 // Evil exit case here : the two last line of the text dump does not contain "."
240 // We should check in a better way (string comparison and such) but it make the whole process to weight a lot more
241 // Conclusion : this is ugly but fast.
242 if ( tmpCurIndex < 0 ) {
243 if ( showDebug == true ) {
244 System.out.println("END OF FILE.");
245 System.out.println();
246 }
247 return null;
248 }
249
250 tracefile = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
251 /*System.out.println(tracefile);*/
252
253 tmpPrevIndex = tmpCurIndex;
254 tmpCurIndex = tmpContent.indexOf(":", tmpPrevIndex);
255 marker = tmpContent.substring(tmpPrevIndex+1, tmpCurIndex ).trim();
256 /*System.out.println(marker);*/
257
258 // Timestamp is next but is presented in second.milisecond format, we have to split them
259 // Sound like :
260 // 952.162637168
261 tmpPrevIndex = tmpCurIndex+1;
262 tmpCurIndex = tmpContent.indexOf(".", tmpPrevIndex);
263 tmpSecond = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
264 /*System.out.println(tmpSecond);*/
265
266 tmpPrevIndex = tmpCurIndex+1;
267 tmpCurIndex = tmpContent.indexOf(" ", tmpPrevIndex);
268 tmpNanosecond = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
269 /*System.out.println(tmpNanosecond);*/
270
271 // We have enough information here to set the timestamp
272 eventTimestamp.setValue( (tmpSecond * 1000000000) + tmpNanosecond );
273 /*System.out.println(eventTimestamp.toString());*/
274
275 // Next field is the reference
276 // A long string enclosed by parenthesis and ending with a comma
277 // (/home/william/workspace/org.eclipse.linuxtools.lttng.tests/traceset/trace-618339events-1293lost-1cpu/kernel_0),
278 tmpPrevIndex = tmpCurIndex+1;
279 tmpCurIndex = tmpContent.indexOf("(", tmpPrevIndex);
280 tmpPrevIndex = tmpCurIndex+1;
281 tmpCurIndex = tmpContent.indexOf("),", tmpPrevIndex);
282 String fullTracePath = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
283 /*System.out.println(fullTracePath);*/
284
285 eventReference.setValue(fullTracePath);
286 String traceName = fullTracePath.substring(fullTracePath.lastIndexOf("/")+1).trim();
287 /*System.out.println(traceName);*/
288 eventReference.setTracepath(traceName);
289
290
291 // The next few fields are relatives to the state system (pid, ppid, etc...) we need to skip them.
292 // They should be like the following :
293 // 4175, 4175, hal-acl-tool, , 4168,
294
295 // 1st comma
296 tmpPrevIndex = tmpCurIndex+1;
297 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
298 // 2nd comma
299 tmpPrevIndex = tmpCurIndex+1;
300 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
301 // 3rd comma
302 tmpPrevIndex = tmpCurIndex+1;
303 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
304 // 4th comma
305 tmpPrevIndex = tmpCurIndex+1;
306 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
307 // 5th comma
308 tmpPrevIndex = tmpCurIndex+1;
309 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
310 // 6th comma
311 tmpPrevIndex = tmpCurIndex+1;
312 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
313
314 // The next field is the CPU, in hexadecimal format
315 // Should be like :
316 // 0x0,
317 tmpPrevIndex = tmpCurIndex+1;
318 tmpCurIndex = tmpContent.indexOf("0x", tmpPrevIndex);
319 tmpPrevIndex = tmpCurIndex+2;
320
321 tmpCurIndex = tmpContent.indexOf(",", tmpPrevIndex);
322 tmpCpu = Long.parseLong( tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim() );
323
324 // Set the cpu number of trace if we found a "new" cpu
325 if ( cpuNumber < (tmpCpu + 1) ) {
326 cpuNumber = (int)(tmpCpu+1);
327 }
328 /*System.out.println(tmpCpu);*/
329
330
331 // The last field is the parsed content
332 // It is enclosed by { }
333 // Look like :
334 // SYSCALL { ip = 0xb7f05422, syscall_id = 221 [sys_fcntl64+0x0/0x79] }
335 //
336 // NOTE : it seems some state system events do not respect this format as they have no payload.
337 // We will create empty payload then.
338 int tmpIndex = tmpContent.indexOf("{", tmpPrevIndex);
339 if ( tmpIndex != -1 ) {
340 tmpPrevIndex = tmpCurIndex+1;
341 tmpCurIndex = tmpIndex;
342 tmpPrevIndex = tmpCurIndex+1;
343 tmpCurIndex = tmpContent.indexOf("}", tmpPrevIndex);
344 parsedPayload = tmpContent.substring(tmpPrevIndex, tmpCurIndex ).trim();
345
346 // Now add each LttngField
347 boolean isDone = false;
348 int tmpIndexBegin = 0;
349 int tmpIndexEqual = 0;
350 int tmpIndexEnd = 0;
351
352 fieldsMap = new HashMap<String, LttngEventField>();
353
354 while ( isDone == false ) {
355 tmpIndexEqual = parsedPayload.indexOf("=", (int)tmpIndexBegin);
356 tmpIndexEnd = parsedPayload.indexOf(", ", (int)tmpIndexEqual);
357 if ( tmpIndexEnd == -1 ) {
358 tmpIndexEnd = parsedPayload.length();
359 isDone = true;
360 }
361
362 markerName = parsedPayload.substring((int)tmpIndexBegin, (int)tmpIndexEqual-1 ).trim();
363 payload = ((String)parsedPayload.substring((int)tmpIndexEqual+1, (int)tmpIndexEnd )).replace("\"", " ").trim();
364
365 // Try to cast the payload into the correct type
366 try {
367 payload = Long.parseLong((String)payload);
368 }
369 catch (NumberFormatException e) { }
370
371 LttngEventField tmpField = new LttngEventField(eventContent, markerName, payload);
372 fieldsMap.put(markerName, tmpField);
373
374 tmpIndexBegin = tmpIndexEnd+1;
375 }
376 }
377 else {
378 fieldsMap = new HashMap<String, LttngEventField>();
379
380 markerName = "";
381 payload = "";
382
383 LttngEventField tmpField = new LttngEventField(eventContent, markerName, payload);
384 fieldsMap.put(markerName, tmpField);
385 }
386
387 eventContent = new TextLttngEventContent(currentLttngEvent, fieldsMap);
388
389 // We now have what we need for the type
390 String tmpTypeKey = tracefile + "/" + tmpCpu + "/" + marker;
391 if ( traceTypes.get(tmpTypeKey) == null ) {
392 traceTypes.put(tmpTypeKey, new LttngEventType(tracefile, tmpCpu, marker, fieldsMap.keySet().toArray(new String[fieldsMap.size()] )) );
393 }
394
395 currentLttngEvent.setContent(eventContent);
396 currentLttngEvent.setType(traceTypes.get(tmpTypeKey));
397
398 returnedEvent = currentLttngEvent;
399 }
400 else if ( showDebug == true ) {
401 System.out.println("NULL READING");
402 System.out.println();
403 returnedEvent = null;
404 }
405 }
406 catch (Exception e) {
407 System.out.println("Pos is :" + nbCharRead);
408 if ( tmpContent != null ) {
409 System.out.println("Erroneous content is :" + tmpContent);
410 }
411
412 tmpContent = null;
413 e.printStackTrace();
414 returnedEvent = null;
415 }
416
417 return returnedEvent;
418 }
419
420 @Override
421 public ITmfLocation<?> getCurrentLocation() {
422 return new TmfLocation<Long>(nbCharRead);
423 }
424
425 @Override
426 public LttngEvent parseEvent(TmfContext context) {
427 context = seekLocation(context.getLocation());
428 return parseMyNextEvent(context);
429
430 }
431
432 public int getCpuNumber() {
433 return cpuNumber;
434 }
435
436 }
437
438
439 // Redefine event to override method we know won't work with a Text tracefile
440 class TextLttngEvent extends LttngEvent {
441
442 public TextLttngEvent( TmfTrace<LttngEvent> parent,
443 LttngTimestamp timestamp,
444 LttngEventSource source,
445 LttngEventType type,
446 LttngEventContent content,
447 LttngEventReference reference)
448 {
449 super(parent, timestamp, source, type, content, reference, null);
450 }
451
452 public TextLttngEvent(TextLttngEvent oldEvent) {
453 this(
454 oldEvent.getParentTrace(),
455 (LttngTimestamp)oldEvent.getTimestamp(),
456 (LttngEventSource)oldEvent.getSource(),
457 (LttngEventType)oldEvent.getType(),
458 (LttngEventContent)oldEvent.getContent(),
459 (LttngEventReference)oldEvent.getReference()
460 );
461 }
462
463 @Override
464 public JniEvent convertEventTmfToJni() {
465 System.out.println("WARNING : Cannot use convertEventTmfToJni() on a trace in text format.");
466 return null;
467 }
468
469 @Override
470 public void updateJniEventReference(JniEvent newJniEventReference) {
471 System.out.println("WARNING : Cannot use updateJniEventReference on a trace in text format. Using null.");
472 }
473 }
474
475
476 class TextLttngEventContent extends LttngEventContent {
477
478 public TextLttngEventContent() {
479 super();
480 }
481
482 public TextLttngEventContent(TextLttngEvent thisParent) {
483 super(thisParent, null);
484 }
485
486 public TextLttngEventContent(TextLttngEvent thisParent, HashMap<String, LttngEventField> thisContent) {
487 super(thisParent, thisContent);
488 }
489
490 public TextLttngEventContent(TextLttngEventContent oldContent) {
491 this( (TextLttngEvent)oldContent.fParentEvent, oldContent.getRawContent());
492 }
493
494 @Override
495 public LttngEventField[] getFields() {
496 return getRawContent().values().toArray(new LttngEventField[getRawContent().size()]);
497 }
498
499 @Override
500 public LttngEventField getField(String name) {
501 LttngEventField returnedField = getRawContent().get(name);
502
503 return returnedField;
504 }
505
506 @Override
507 public LttngEventField getField(int position) {
508 LttngEventField returnedField = null;
509 String label = null;
510 try {
511 label = fParentEvent.getType().getLabel(position);
512 returnedField = this.getField(label);
513 }
514 catch (TmfNoSuchFieldException e) {
515 System.out.println("Invalid field position requested : " + position + ", ignoring (getField).");
516 }
517
518 return returnedField;
519 }
520 }
This page took 0.041102 seconds and 5 git commands to generate.