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