tmf: Remove the ITmfEventTableColumns extension point
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / parsers / custom / CustomTxtTrace.java
CommitLineData
6151d86c 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2010, 2014 Ericsson
6151d86c
PT
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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
2bdf0193 13package org.eclipse.tracecompass.tmf.core.parsers.custom;
6151d86c 14
eb8ea213 15import java.io.File;
6151d86c
PT
16import java.io.FileNotFoundException;
17import java.io.IOException;
032ecd45 18import java.nio.ByteBuffer;
6151d86c
PT
19import java.util.HashMap;
20import java.util.Iterator;
21import java.util.List;
22import java.util.Map.Entry;
23import java.util.regex.Matcher;
24
25import org.eclipse.core.resources.IProject;
26import org.eclipse.core.resources.IResource;
a94410d9
MK
27import org.eclipse.core.runtime.IStatus;
28import org.eclipse.core.runtime.Status;
2bdf0193 29import org.eclipse.tracecompass.internal.tmf.core.Activator;
b04903a2 30import org.eclipse.tracecompass.internal.tmf.core.parsers.custom.CustomEventAspects;
2bdf0193 31import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
b04903a2 32import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
2bdf0193
AM
33import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
34import org.eclipse.tracecompass.tmf.core.io.BufferedRandomAccessFile;
35import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition.InputLine;
36import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
37import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
38import org.eclipse.tracecompass.tmf.core.trace.ITmfEventParser;
39import org.eclipse.tracecompass.tmf.core.trace.TmfContext;
40import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
41import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
42import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfPersistentlyIndexable;
43import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer;
44import org.eclipse.tracecompass.tmf.core.trace.indexer.TmfBTreeTraceIndexer;
45import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint;
46import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
47import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
48import org.eclipse.tracecompass.tmf.core.trace.location.TmfLongLocation;
6151d86c 49
a0a88f65
AM
50/**
51 * Base class for custom plain text traces.
52 *
53 * @author Patrick Tassé
47aafe74 54 * @since 3.0
a0a88f65 55 */
032ecd45 56public class CustomTxtTrace extends TmfTrace implements ITmfEventParser, ITmfPersistentlyIndexable {
6151d86c 57
661becf8 58 private static final TmfLongLocation NULL_LOCATION = new TmfLongLocation(-1L);
6151d86c 59 private static final int DEFAULT_CACHE_SIZE = 100;
cd43d683
PT
60 private static final int MAX_LINES = 100;
61 private static final int MAX_CONFIDENCE = 100;
6151d86c
PT
62
63 private final CustomTxtTraceDefinition fDefinition;
64 private final CustomTxtEventType fEventType;
65 private BufferedRandomAccessFile fFile;
66
a0a88f65
AM
67 /**
68 * Basic constructor.
69 *
70 * @param definition
71 * Text trace definition
72 */
6151d86c
PT
73 public CustomTxtTrace(final CustomTxtTraceDefinition definition) {
74 fDefinition = definition;
75 fEventType = new CustomTxtEventType(fDefinition);
76 setCacheSize(DEFAULT_CACHE_SIZE);
77 }
78
a0a88f65
AM
79 /**
80 * Full constructor.
81 *
82 * @param resource
83 * Trace's resource.
84 * @param definition
85 * Text trace definition
86 * @param path
87 * Path to the trace file
88 * @param cacheSize
89 * Cache size to use
90 * @throws TmfTraceException
91 * If we couldn't open the trace at 'path'
92 */
93 public CustomTxtTrace(final IResource resource,
94 final CustomTxtTraceDefinition definition, final String path,
95 final int cacheSize) throws TmfTraceException {
6151d86c
PT
96 this(definition);
97 setCacheSize((cacheSize > 0) ? cacheSize : DEFAULT_CACHE_SIZE);
98 initTrace(resource, path, CustomTxtEvent.class);
99 }
100
101 @Override
102 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> eventType) throws TmfTraceException {
103 super.initTrace(resource, path, eventType);
104 try {
105 fFile = new BufferedRandomAccessFile(getPath(), "r"); //$NON-NLS-1$
106 } catch (IOException e) {
107 throw new TmfTraceException(e.getMessage(), e);
108 }
6151d86c
PT
109 }
110
111 @Override
112 public synchronized void dispose() {
113 super.dispose();
114 if (fFile != null) {
115 try {
116 fFile.close();
117 } catch (IOException e) {
118 } finally {
119 fFile = null;
120 }
121 }
122 }
123
b0422293
PT
124 @Override
125 public ITmfTraceIndexer getIndexer() {
126 return super.getIndexer();
127 }
128
b04903a2
AM
129 @Override
130 public Iterable<ITmfEventAspect> getEventAspects() {
131 return CustomEventAspects.generateAspects(fDefinition);
132 }
133
6151d86c
PT
134 @Override
135 public synchronized TmfContext seekEvent(final ITmfLocation location) {
136 final CustomTxtTraceContext context = new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
137 if (NULL_LOCATION.equals(location) || fFile == null) {
138 return context;
139 }
140 try {
141 if (location == null) {
142 fFile.seek(0);
143 } else if (location.getLocationInfo() instanceof Long) {
144 fFile.seek((Long) location.getLocationInfo());
145 }
6151d86c 146 long rawPos = fFile.getFilePointer();
cd43d683
PT
147 String line = fFile.getNextLine();
148 while (line != null) {
6151d86c
PT
149 for (final InputLine input : getFirstLines()) {
150 final Matcher matcher = input.getPattern().matcher(line);
03e9dbb7 151 if (matcher.matches()) {
6151d86c
PT
152 context.setLocation(new TmfLongLocation(rawPos));
153 context.firstLineMatcher = matcher;
154 context.firstLine = line;
155 context.nextLineLocation = fFile.getFilePointer();
156 context.inputLine = input;
157 return context;
158 }
159 }
160 rawPos = fFile.getFilePointer();
cd43d683 161 line = fFile.getNextLine();
6151d86c
PT
162 }
163 return context;
164 } catch (final FileNotFoundException e) {
47aafe74 165 Activator.logError("Error seeking event. File not found: " + getPath(), e); //$NON-NLS-1$
6151d86c
PT
166 return context;
167 } catch (final IOException e) {
47aafe74 168 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
6151d86c
PT
169 return context;
170 }
171
172 }
173
174 @Override
175 public synchronized TmfContext seekEvent(final double ratio) {
176 if (fFile == null) {
177 return new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
178 }
179 try {
91f6e587 180 long pos = Math.round(ratio * fFile.length());
6151d86c
PT
181 while (pos > 0) {
182 fFile.seek(pos - 1);
183 if (fFile.read() == '\n') {
184 break;
185 }
186 pos--;
187 }
188 final ITmfLocation location = new TmfLongLocation(pos);
189 final TmfContext context = seekEvent(location);
190 context.setRank(ITmfContext.UNKNOWN_RANK);
191 return context;
192 } catch (final IOException e) {
47aafe74 193 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
6151d86c
PT
194 return new CustomTxtTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
195 }
196 }
197
198 @Override
199 public synchronized double getLocationRatio(final ITmfLocation location) {
200 if (fFile == null) {
201 return 0;
202 }
203 try {
204 if (location.getLocationInfo() instanceof Long) {
0126a8ca 205 return ((Long) location.getLocationInfo()).doubleValue() / fFile.length();
6151d86c
PT
206 }
207 } catch (final IOException e) {
47aafe74 208 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
6151d86c
PT
209 }
210 return 0;
211 }
212
213 @Override
214 public ITmfLocation getCurrentLocation() {
215 // TODO Auto-generated method stub
216 return null;
217 }
218
219 @Override
220 public synchronized CustomTxtEvent parseEvent(final ITmfContext tmfContext) {
221 ITmfContext context = seekEvent(tmfContext.getLocation());
222 return parse(context);
223 }
224
225 @Override
226 public synchronized CustomTxtEvent getNext(final ITmfContext context) {
4c9f2944 227 final ITmfContext savedContext = new TmfContext(context.getLocation(), context.getRank());
6151d86c
PT
228 final CustomTxtEvent event = parse(context);
229 if (event != null) {
230 updateAttributes(savedContext, event.getTimestamp());
231 context.increaseRank();
232 }
233 return event;
234 }
235
236 private synchronized CustomTxtEvent parse(final ITmfContext tmfContext) {
237 if (fFile == null) {
238 return null;
239 }
240 if (!(tmfContext instanceof CustomTxtTraceContext)) {
241 return null;
242 }
243
244 final CustomTxtTraceContext context = (CustomTxtTraceContext) tmfContext;
9cbe7899 245 if (context.getLocation() == null || !(context.getLocation().getLocationInfo() instanceof Long) || NULL_LOCATION.equals(context.getLocation())) {
6151d86c
PT
246 return null;
247 }
248
249 CustomTxtEvent event = parseFirstLine(context);
250
507b1336 251 final HashMap<InputLine, Integer> countMap = new HashMap<>();
6151d86c
PT
252 InputLine currentInput = null;
253 if (context.inputLine.childrenInputs != null && context.inputLine.childrenInputs.size() > 0) {
254 currentInput = context.inputLine.childrenInputs.get(0);
255 countMap.put(currentInput, 0);
256 }
257
258 try {
259 if (fFile.getFilePointer() != context.nextLineLocation) {
260 fFile.seek(context.nextLineLocation);
261 }
6151d86c 262 long rawPos = fFile.getFilePointer();
cd43d683
PT
263 String line = fFile.getNextLine();
264 while (line != null) {
6151d86c
PT
265 boolean processed = false;
266 if (currentInput == null) {
267 for (final InputLine input : getFirstLines()) {
268 final Matcher matcher = input.getPattern().matcher(line);
03e9dbb7 269 if (matcher.matches()) {
6151d86c
PT
270 context.setLocation(new TmfLongLocation(rawPos));
271 context.firstLineMatcher = matcher;
272 context.firstLine = line;
273 context.nextLineLocation = fFile.getFilePointer();
274 context.inputLine = input;
275 return event;
276 }
277 }
278 } else {
279 if (countMap.get(currentInput) >= currentInput.getMinCount()) {
280 final List<InputLine> nextInputs = currentInput.getNextInputs(countMap);
281 if (nextInputs.size() == 0 || nextInputs.get(nextInputs.size() - 1).getMinCount() == 0) {
282 for (final InputLine input : getFirstLines()) {
283 final Matcher matcher = input.getPattern().matcher(line);
03e9dbb7 284 if (matcher.matches()) {
6151d86c
PT
285 context.setLocation(new TmfLongLocation(rawPos));
286 context.firstLineMatcher = matcher;
287 context.firstLine = line;
288 context.nextLineLocation = fFile.getFilePointer();
289 context.inputLine = input;
290 return event;
291 }
292 }
293 }
294 for (final InputLine input : nextInputs) {
295 final Matcher matcher = input.getPattern().matcher(line);
03e9dbb7 296 if (matcher.matches()) {
6151d86c
PT
297 event.processGroups(input, matcher);
298 currentInput = input;
299 if (countMap.get(currentInput) == null) {
300 countMap.put(currentInput, 1);
301 } else {
302 countMap.put(currentInput, countMap.get(currentInput) + 1);
303 }
304 Iterator<InputLine> iter = countMap.keySet().iterator();
305 while (iter.hasNext()) {
306 final InputLine inputLine = iter.next();
307 if (inputLine.level > currentInput.level) {
308 iter.remove();
309 }
310 }
311 if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {
312 currentInput = currentInput.childrenInputs.get(0);
313 countMap.put(currentInput, 0);
314 } else if (countMap.get(currentInput) >= currentInput.getMaxCount()) {
315 if (currentInput.getNextInputs(countMap).size() > 0) {
316 currentInput = currentInput.getNextInputs(countMap).get(0);
317 if (countMap.get(currentInput) == null) {
318 countMap.put(currentInput, 0);
319 }
320 iter = countMap.keySet().iterator();
321 while (iter.hasNext()) {
322 final InputLine inputLine = iter.next();
323 if (inputLine.level > currentInput.level) {
324 iter.remove();
325 }
326 }
327 } else {
328 currentInput = null;
329 }
330 }
331 processed = true;
332 break;
333 }
334 }
335 }
3dca7aa5 336 if (!processed && currentInput != null) {
6151d86c 337 final Matcher matcher = currentInput.getPattern().matcher(line);
03e9dbb7 338 if (matcher.matches()) {
6151d86c
PT
339 event.processGroups(currentInput, matcher);
340 countMap.put(currentInput, countMap.get(currentInput) + 1);
341 if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {
342 currentInput = currentInput.childrenInputs.get(0);
343 countMap.put(currentInput, 0);
344 } else if (countMap.get(currentInput) >= currentInput.getMaxCount()) {
345 if (currentInput.getNextInputs(countMap).size() > 0) {
346 currentInput = currentInput.getNextInputs(countMap).get(0);
347 if (countMap.get(currentInput) == null) {
348 countMap.put(currentInput, 0);
349 }
350 final Iterator<InputLine> iter = countMap.keySet().iterator();
351 while (iter.hasNext()) {
352 final InputLine inputLine = iter.next();
353 if (inputLine.level > currentInput.level) {
354 iter.remove();
355 }
356 }
357 } else {
358 currentInput = null;
359 }
360 }
361 }
362 ((StringBuffer) event.getContent().getValue()).append("\n").append(line); //$NON-NLS-1$
363 }
364 }
365 rawPos = fFile.getFilePointer();
cd43d683 366 line = fFile.getNextLine();
6151d86c
PT
367 }
368 } catch (final IOException e) {
47aafe74 369 Activator.logError("Error seeking event. File: " + getPath(), e); //$NON-NLS-1$
6151d86c
PT
370 }
371 for (final Entry<InputLine, Integer> entry : countMap.entrySet()) {
372 if (entry.getValue() < entry.getKey().getMinCount()) {
373 event = null;
374 }
375 }
376 context.setLocation(NULL_LOCATION);
377 return event;
378 }
379
a0a88f65
AM
380 /**
381 * @return The first few lines of the text file
382 */
6151d86c
PT
383 public List<InputLine> getFirstLines() {
384 return fDefinition.inputs;
385 }
386
a0a88f65
AM
387 /**
388 * Parse the first line of the trace (to recognize the type).
389 *
390 * @param context
391 * Trace context
392 * @return The first event
393 */
6151d86c 394 public CustomTxtEvent parseFirstLine(final CustomTxtTraceContext context) {
e1de2fd4 395 final CustomTxtEvent event = new CustomTxtEvent(fDefinition, this, TmfTimestamp.ZERO, fEventType);
6151d86c
PT
396 event.processGroups(context.inputLine, context.firstLineMatcher);
397 event.setContent(new CustomEventContent(event, new StringBuffer(context.firstLine)));
398 return event;
399 }
400
a0a88f65
AM
401 /**
402 * Get the trace definition.
403 *
404 * @return The trace definition
405 */
6151d86c
PT
406 public CustomTraceDefinition getDefinition() {
407 return fDefinition;
408 }
409
cd43d683
PT
410 /**
411 * {@inheritDoc}
412 * <p>
413 * The default implementation computes the confidence as the percentage of
414 * lines in the first 100 lines of the file which match any of the root
415 * input line patterns.
416 */
6151d86c 417 @Override
a94410d9 418 public IStatus validate(IProject project, String path) {
eb8ea213 419 File file = new File(path);
cd43d683
PT
420 if (!file.exists() || !file.isFile() || !file.canRead()) {
421 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CustomTrace_FileNotFound + ": " + path); //$NON-NLS-1$
422 }
423 int confidence = 0;
424 try (BufferedRandomAccessFile rafile = new BufferedRandomAccessFile(path, "r")) { //$NON-NLS-1$
425 int lineCount = 0;
918551aa 426 double matches = 0.0;
cd43d683
PT
427 String line = rafile.getNextLine();
428 while ((line != null) && (lineCount++ < MAX_LINES)) {
429 for (InputLine inputLine : fDefinition.inputs) {
430 Matcher matcher = inputLine.getPattern().matcher(line);
03e9dbb7 431 if (matcher.matches()) {
918551aa
BH
432 int groupCount = matcher.groupCount();
433 matches += (1.0 + groupCount / ((double) groupCount + 1));
cd43d683
PT
434 break;
435 }
436 }
918551aa 437 confidence = (int) (MAX_CONFIDENCE * matches / lineCount);
cd43d683
PT
438 line = rafile.getNextLine();
439 }
440 } catch (IOException e) {
441 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
a94410d9 442 }
cd43d683 443 return new TraceValidationStatus(confidence, Activator.PLUGIN_ID);
6151d86c 444 }
032ecd45
MAL
445
446 private static int fCheckpointSize = -1;
447
448 @Override
449 public synchronized int getCheckpointSize() {
450 if (fCheckpointSize == -1) {
451 TmfCheckpoint c = new TmfCheckpoint(TmfTimestamp.ZERO, new TmfLongLocation(0L), 0);
452 ByteBuffer b = ByteBuffer.allocate(ITmfCheckpoint.MAX_SERIALIZE_SIZE);
453 b.clear();
454 c.serialize(b);
455 fCheckpointSize = b.position();
456 }
457
458 return fCheckpointSize;
459 }
460
461 @Override
462 public ITmfLocation restoreLocation(ByteBuffer bufferIn) {
463 return new TmfLongLocation(bufferIn);
464 }
465
466 @Override
467 protected ITmfTraceIndexer createIndexer(int interval) {
468 return new TmfBTreeTraceIndexer(this, interval);
469 }
6151d86c 470}
This page took 0.08579 seconds and 5 git commands to generate.