Move alltests plugin to the Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.tracecompass.btf.core / src / org / eclipse / linuxtools / btf / core / trace / BtfTrace.java
CommitLineData
ff71e543
MK
1/*******************************************************************************
2 * Copyright (c) 2014 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 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.btf.core.trace;
14
15import java.io.File;
16import java.io.FileNotFoundException;
17import java.io.IOException;
18import java.io.RandomAccessFile;
19import java.nio.ByteBuffer;
20import java.text.ParseException;
21import java.text.SimpleDateFormat;
22import java.util.Date;
23import java.util.HashMap;
24import java.util.Map;
25import java.util.TreeMap;
26
27import org.eclipse.core.resources.IProject;
28import org.eclipse.core.resources.IResource;
29import org.eclipse.core.runtime.IStatus;
30import org.eclipse.core.runtime.Status;
31import org.eclipse.linuxtools.btf.core.Activator;
32import org.eclipse.linuxtools.btf.core.event.BtfEvent;
33import org.eclipse.linuxtools.btf.core.event.BtfEventType;
34import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
35import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
36import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
37import org.eclipse.linuxtools.tmf.core.io.BufferedRandomAccessFile;
38import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtTraceContext;
39import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
40import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
41import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;
42import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
43import org.eclipse.linuxtools.tmf.core.trace.TmfContext;
44import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
45import org.eclipse.linuxtools.tmf.core.trace.TraceValidationStatus;
46import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
47import org.eclipse.linuxtools.tmf.core.trace.indexer.ITmfTraceIndexer;
48import org.eclipse.linuxtools.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
49import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
50import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
51import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
52import org.eclipse.linuxtools.tmf.core.trace.location.TmfLongLocation;
53
54import com.google.common.collect.ImmutableMap;
55
56/**
57 * BTF reader. Reads Best Trace Format traces.
58 *
59 * @author Matthew Khouzam
60 */
61public class BtfTrace extends TmfTrace implements ITmfEventParser, ITmfPersistentlyIndexable, ITmfTraceProperties, AutoCloseable {
62
63 private static final String VERSION = "#version"; //$NON-NLS-1$
64 private static final String CREATOR = "#creator"; //$NON-NLS-1$
65 private static final String CREATIONDATE = "#creationDate"; //$NON-NLS-1$
66 private static final String INPUTFILE = "#inputFile"; //$NON-NLS-1$
67 private static final String TIMESCALE = "#timeScale"; //$NON-NLS-1$
68 private static final String ENTITYTYPE = "#entityType"; //$NON-NLS-1$
69 private static final String ENTITYTABLE = "#entityTable"; //$NON-NLS-1$
70 private static final String ENTITYTYPETABLE = "#entityTypeTable"; //$NON-NLS-1$
71
72 // lower-case helpers
73 private static final String lCREATIONDATE = "#creationdate"; //$NON-NLS-1$
74 private static final String lINPUTFILE = "#inputfile"; //$NON-NLS-1$
75 private static final String lTIMESCALE = "#timescale"; //$NON-NLS-1$
76 private static final String lENTITYTYPE = "#entitytype"; //$NON-NLS-1$
77 private static final String lENTITYTABLE = "#entitytable"; //$NON-NLS-1$
78 private static final String lENTITYTYPETABLE = "#entitytypetable"; //$NON-NLS-1$
79
80 private static final TmfLongLocation NULL_LOCATION = new TmfLongLocation(-1L);
81
82 private static final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); //$NON-NLS-1$
83
84 private static final int CACHE_SIZE = 256;
85 private static final int MAX_CONFIDENCE = 100;
86 private static final int MAX_LINES = 100;
87
88 private static int fCheckpointSize = -1;
89
90 private final Map<String, String> fProperties = new HashMap<>();
91
92 private final Map<Integer, String> fEntityTable = new TreeMap<>();
93 private final Map<BtfEventType, String> fEntityTypeTable = new HashMap<>();
94 private final Map<Integer, BtfEventType> fEntityTypes = new TreeMap<>();
95
96 private String fVersion;
97 private String fCreator;
98 private String fCreationDate;
99 private String fInputFile;
100 // default unit is ns
101 private BtfTimstampFormat fTsFormat = BtfTimstampFormat.NS;
102
103 private File fFile;
104 private RandomAccessFile fFileInput;
105 private long fDataOffset;
106 private long fTsOffset = 0;
107
108 /**
109 * Default constructor
110 */
111 public BtfTrace() {
112 super();
113 setCacheSize(CACHE_SIZE);
114 fProperties.put(TIMESCALE, fTsFormat.toString());
115 }
116
117 private void parseHeader(RandomAccessFile input) throws IOException {
118 String line = input.readLine();
119 long pos = 0;
120 while (line != null && line.startsWith("#")) { //$NON-NLS-1$
121 String[] tokens = line.split(" ", 2); //$NON-NLS-1$
122 /*
123 * please note that the examples we were given and the spec are NOT
124 * consistent, so we are ignoring the case to avoid issues
125 */
126 switch (tokens[0].toLowerCase()) {
127 case VERSION:
128 fVersion = tokens[1];
129 fProperties.put(VERSION, fVersion);
130 break;
131 case CREATOR:
132 fCreator = tokens[1];
133 fProperties.put(CREATOR, fCreator);
134 break;
135 case lCREATIONDATE:
136 fCreationDate = tokens[1];
137 fProperties.put(CREATIONDATE, fCreationDate);
138
139 try {
140 Date dateTime = ISO8601DATEFORMAT.parse(fCreationDate);
141 fTsOffset = dateTime.getTime() * 1000000L;
142 } catch (ParseException e) {
143 Activator.logWarning("Creation date error: " + e.getMessage()); //$NON-NLS-1$
144 }
145 break;
146 case lINPUTFILE:
147 fInputFile = tokens[1];
148 fProperties.put(INPUTFILE, fInputFile);
149 break;
150 case lTIMESCALE:
151 fTsFormat = BtfTimstampFormat.parse(tokens[1]);
152 fProperties.put(TIMESCALE, fTsFormat.toString());
153 break;
154 case lENTITYTYPE:
155 pos = fFileInput.getFilePointer();
156 line = fFileInput.readLine();
157 while (line.startsWith("#-")) { //$NON-NLS-1$
158 String tempLine = line.substring(1);
159 String[] elements = tempLine.split(" ", 2); //$NON-NLS-1$
160 fEntityTypes.put(Integer.parseInt(elements[0]), BtfEventTypeFactory.parse(elements[1]));
161 pos = fFileInput.getFilePointer();
162 line = fFileInput.readLine();
163 }
164 fFileInput.seek(pos);
165 fProperties.put(ENTITYTYPE, fEntityTypes.toString());
166 break;
167 case lENTITYTABLE:
168 pos = fFileInput.getFilePointer();
169 line = fFileInput.readLine();
170 while (line.startsWith("#-")) { //$NON-NLS-1$
171 String tempLine = line.substring(1);
172 String[] elements = tempLine.split(" ", 2); //$NON-NLS-1$
173 fEntityTable.put(Integer.parseInt(elements[0]), elements[1]);
174 pos = fFileInput.getFilePointer();
175 line = fFileInput.readLine();
176 }
177 fProperties.put(ENTITYTABLE, fEntityTable.toString());
178 fFileInput.seek(pos);
179 break;
180 case lENTITYTYPETABLE:
181 pos = fFileInput.getFilePointer();
182 line = fFileInput.readLine();
183 while (line.startsWith("#-")) { //$NON-NLS-1$
184 String tempLine = line.substring(1);
185 String[] elements = tempLine.split(" ", 2); //$NON-NLS-1$
186 fEntityTypeTable.put(BtfEventTypeFactory.parse(elements[0]), elements[1]);
187 pos = fFileInput.getFilePointer();
188 line = fFileInput.readLine();
189 }
190 fFileInput.seek(pos);
191 fProperties.put(ENTITYTYPETABLE, fEntityTypeTable.toString());
192 break;
193 default:
194 break;
195 }
196 fDataOffset = input.getFilePointer();
197 line = input.readLine();
198 }
199 fTsOffset = (long) (fTsOffset * fTsFormat.getScaleFactor());
200 }
201
202 @Override
203 public void initTrace(IResource resource, String path, Class<? extends ITmfEvent> type) throws TmfTraceException {
204 super.initTrace(resource, path, type);
205 fFile = new File(path);
206 try {
207 fFileInput = new RandomAccessFile(fFile, "r"); //$NON-NLS-1$
208 parseHeader(fFileInput);
209 } catch (IOException e) {
5c9bdcbe 210 throw new TmfTraceException(e.getMessage(), e);
ff71e543
MK
211 }
212
213 }
214
215 @Override
216 public IStatus validate(IProject project, String path) {
217 File file = new File(path);
218 if (!file.exists()) {
219 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "File not found: " + path); //$NON-NLS-1$
220 }
221 if (!file.isFile()) {
222 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Not a file. It's a directory: " + path); //$NON-NLS-1$
223 }
224 int confidence = 0;
225 try (BufferedRandomAccessFile rafile = new BufferedRandomAccessFile(path, "r")) { //$NON-NLS-1$
226 int lineCount = 0;
227 int matches = 0;
228 String line = rafile.getNextLine();
229 while ((line != null) && line.startsWith("#")) { //$NON-NLS-1$
230 line = rafile.getNextLine();
231 }
232 while ((line != null) && (lineCount++ < MAX_LINES)) {
233 try {
234 ITmfEvent event = parseLine(0, line);
235 if (event != null) {
236 matches++;
237 }
238 } catch (RuntimeException e) {
239 confidence = Integer.MIN_VALUE;
240 }
241
242 confidence = MAX_CONFIDENCE * matches / lineCount;
243 line = rafile.getNextLine();
244 }
245 } catch (IOException e) {
246 Activator.logError("Error validating file: " + path, e); //$NON-NLS-1$
247 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
248 }
249
250 return new TraceValidationStatus(confidence, Activator.PLUGIN_ID);
251 }
252
253 @Override
254 public ITmfLocation getCurrentLocation() {
255 long temp = -1;
256 try {
257 temp = fFileInput.getFilePointer();
258 } catch (IOException e) {
259 }
260 return new TmfLongLocation(temp);
261 }
262
263 @Override
264 public double getLocationRatio(ITmfLocation location) {
265 long size = fFile.length() - fDataOffset;
266 long pos;
267 try {
268 pos = fFileInput.getFilePointer() - fDataOffset;
269 } catch (IOException e) {
270 pos = 0;
271 }
272 return 1.0 / size * pos;
273 }
274
275 @Override
276 public ITmfContext seekEvent(ITmfLocation location) {
277 final TmfContext context = new TmfContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
278 if (NULL_LOCATION.equals(location) || fFile == null) {
279 return context;
280 }
281 try {
282 if (location == null) {
283 fFileInput.seek(fDataOffset);
284 } else if (location.getLocationInfo() instanceof Long) {
285 fFileInput.seek((Long) location.getLocationInfo());
286 }
287 context.setLocation(new TmfLongLocation(fFileInput.getFilePointer()));
288 return context;
289 } catch (final FileNotFoundException e) {
290 Activator.logError("Error seeking event. File not found: " + getPath(), e); //$NON-NLS-1$
291 return context;
292 } catch (final IOException e) {
293 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
294 return context;
295 }
296 }
297
298 @Override
299 public ITmfContext seekEvent(double ratio) {
300 if (fFile == null) {
301 return new TmfContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
302 }
303 try {
304 long pos = Math.round(ratio * fFile.length()) - fDataOffset;
305 while (pos > 0) {
306 fFileInput.seek(pos - 1);
307 if (fFileInput.read() == '\n') {
308 break;
309 }
310 pos--;
311 }
312 final ITmfLocation location = new TmfLongLocation(pos);
313 final ITmfContext context = seekEvent(location);
314 context.setRank(ITmfContext.UNKNOWN_RANK);
315 return context;
316 } catch (final IOException e) {
317 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
318 return new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
319 }
320 }
321
322 @Override
323 public ITmfEvent parseEvent(ITmfContext tmfContext) {
324 if (fFile == null || (!(tmfContext instanceof TmfContext))) {
325 return null;
326 }
327
328 final TmfContext context = (TmfContext) tmfContext;
329 if (context.getLocation() == null
330 || !(context.getLocation().getLocationInfo() instanceof Long)
331 || NULL_LOCATION.equals(context.getLocation())) {
332 return null;
333 }
334
335 return parseLine(context);
336
337 }
338
339 /**
340 * Parse a line with a context
341 *
342 * @param context
343 * the context, has a location
344 * @return the event from a given line
345 */
346 private ITmfEvent parseLine(TmfContext context) {
347 try {
348 if (!context.getLocation().getLocationInfo().equals(fFileInput.getFilePointer())) {
349 seekEvent(context.getLocation());
350 }
351 } catch (IOException e1) {
352 seekEvent(context.getLocation());
353 }
354 String line;
355 try {
356 line = fFileInput.readLine();
357 return parseLine(context.getRank(), line);
358
359 } catch (IOException e) {
360 }
361
362 return null;
363 }
364
365 /**
366 * Parse a line of text and make an event using it.
367 *
368 * @param rank
369 * the rank of the event
370 * @param line
371 * the raw string of the event
372 * @return the event
373 */
374 private ITmfEvent parseLine(long rank, String line) {
375 if (line == null) {
376 return null;
377 }
378 String[] tokens = line.split(",", 7); //$NON-NLS-1$
379 long timestamp = Long.parseLong(tokens[0]);
380 String source = tokens[1];
381 long sourceInstance = Long.parseLong(tokens[2]);
382 BtfEventType type = BtfEventTypeFactory.parse(tokens[3]);
383 String target = tokens[4];
384 long targetInstance = Long.parseLong(tokens[5]);
385 String event = tokens[6];
386
387 ITmfEventField content = type.generateContent(event, sourceInstance, targetInstance);
388
389 return new BtfEvent(this, rank,
6b44794a 390 getTimestampTransform().transform(fTsFormat.createTimestamp(timestamp + fTsOffset)),
ff71e543
MK
391 source,
392 type,
393 type.getDescription(),
394 content,
395 target);
396 }
397
398 @Override
399 public int getCheckpointSize() {
400 synchronized (getClass()) {
401 if (fCheckpointSize == -1) {
402 TmfCheckpoint c = new TmfCheckpoint(TmfTimestamp.ZERO, new TmfLongLocation(0L), 0);
403 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
404 b.clear();
405 c.serialize(b);
406 fCheckpointSize = b.position();
407 }
408 }
409
410 return fCheckpointSize;
411 }
412
413 @Override
414 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
415 return new TmfLongLocation(bufferIn);
416 }
417
418 @Override
419 protected ITmfTraceIndexer createIndexer(int interval) {
420 return new TmfBTreeTraceIndexer(this, interval);
421 }
422
423 @Override
424 public Map<String, String> getTraceProperties() {
425 return ImmutableMap.copyOf(fProperties);
426 }
427
428 @Override
429 public void close() throws IOException {
430 if (fFileInput != null) {
431 fFileInput.close();
432 }
433 }
434
435}
This page took 0.058477 seconds and 5 git commands to generate.