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