TMF: Changed the LTTng kernel analysis module to use the output extension
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFTraceReader.java
CommitLineData
866e5b51 1/*******************************************************************************
93a45b54 2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 *
4311ac8b
MAL
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Alexandre Montplaisir - Initial API and implementation
866e5b51
FC
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.ctf.core.trace;
15
0594c61c 16import java.util.ArrayList;
0594c61c 17import java.util.List;
866e5b51
FC
18import java.util.PriorityQueue;
19import java.util.Set;
866e5b51 20
866e5b51 21import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
a9d52b8f 22import org.eclipse.linuxtools.internal.ctf.core.Activator;
ce2388e0
FC
23import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputReaderTimestampComparator;
24
866e5b51 25/**
d37aaa7f 26 * A CTF trace reader. Reads the events of a trace.
1d7277f3 27 *
d37aaa7f
FC
28 * @version 1.0
29 * @author Matthew Khouzam
30 * @author Alexandre Montplaisir
866e5b51 31 */
866e5b51
FC
32public class CTFTraceReader {
33
34 // ------------------------------------------------------------------------
35 // Attributes
36 // ------------------------------------------------------------------------
37
38 /**
39 * The trace to read from.
40 */
93a45b54 41 private final CTFTrace fTrace;
866e5b51
FC
42
43 /**
44 * Vector of all the trace file readers.
45 */
93a45b54 46 private final List<StreamInputReader> fStreamInputReaders = new ArrayList<>();
866e5b51
FC
47
48 /**
49 * Priority queue to order the trace file readers by timestamp.
50 */
93a45b54 51 private PriorityQueue<StreamInputReader> fPrio;
866e5b51
FC
52
53 /**
54 * Array to count the number of event per trace file.
55 */
93a45b54 56 private long[] fEventCountPerTraceFile;
866e5b51
FC
57
58 /**
59 * Timestamp of the first event in the trace
60 */
93a45b54 61 private long fStartTime;
866e5b51
FC
62
63 /**
64 * Timestamp of the last event read so far
65 */
93a45b54 66 private long fEndTime;
866e5b51
FC
67
68 // ------------------------------------------------------------------------
69 // Constructors
70 // ------------------------------------------------------------------------
71
72 /**
73 * Constructs a TraceReader to read a trace.
74 *
75 * @param trace
76 * The trace to read from.
db8e8f7d
AM
77 * @throws CTFReaderException
78 * if an error occurs
866e5b51 79 */
db8e8f7d 80 public CTFTraceReader(CTFTrace trace) throws CTFReaderException {
93a45b54
MK
81 fTrace = trace;
82 fStreamInputReaders.clear();
866e5b51
FC
83
84 /**
85 * Create the trace file readers.
86 */
87 createStreamInputReaders();
88
89 /**
90 * Populate the timestamp-based priority queue.
91 */
92 populateStreamInputReaderHeap();
93
94 /**
bfe038ff
MK
95 * Get the start Time of this trace bear in mind that the trace could be
96 * empty.
866e5b51 97 */
93a45b54 98 fStartTime = 0;
33656d8e 99 if (hasMoreEvents()) {
93a45b54
MK
100 fStartTime = fPrio.peek().getCurrentEvent().getTimestamp();
101 setEndTime(fStartTime);
33656d8e 102 }
866e5b51
FC
103 }
104
105 /**
106 * Copy constructor
be6df2d8
AM
107 *
108 * @return The new CTFTraceReader
db8e8f7d 109 * @throws CTFReaderException if an error occurs
866e5b51 110 */
db8e8f7d 111 public CTFTraceReader copyFrom() throws CTFReaderException {
866e5b51
FC
112 CTFTraceReader newReader = null;
113
93a45b54
MK
114 newReader = new CTFTraceReader(fTrace);
115 newReader.fStartTime = fStartTime;
116 newReader.setEndTime(fEndTime);
866e5b51
FC
117 return newReader;
118 }
119
5d1c6919
PT
120 /**
121 * Dispose the CTFTraceReader
db8e8f7d 122 *
5d1c6919
PT
123 * @since 2.0
124 */
125 public void dispose() {
93a45b54 126 for (StreamInputReader reader : fStreamInputReaders) {
5d1c6919
PT
127 if (reader != null) {
128 reader.dispose();
129 }
130 }
93a45b54 131 fStreamInputReaders.clear();
5d1c6919
PT
132 }
133
866e5b51
FC
134 // ------------------------------------------------------------------------
135 // Getters/Setters/Predicates
136 // ------------------------------------------------------------------------
137
138 /**
139 * Return the start time of this trace (== timestamp of the first event)
140 *
0d9a6d76 141 * @return the trace start time
866e5b51
FC
142 */
143 public long getStartTime() {
93a45b54 144 return fStartTime;
866e5b51
FC
145 }
146
6f4e8ec0
AM
147 /**
148 * Set the trace's end time
149 *
150 * @param endTime
151 * The end time to use
152 */
0594c61c 153 protected final void setEndTime(long endTime) {
93a45b54 154 fEndTime = endTime;
6f4e8ec0
AM
155 }
156
0594c61c
AM
157 /**
158 * Get the priority queue of this trace reader.
159 *
160 * @return The priority queue of input readers
161 * @since 2.0
162 */
163 protected PriorityQueue<StreamInputReader> getPrio() {
93a45b54 164 return fPrio;
0594c61c
AM
165 }
166
866e5b51
FC
167 // ------------------------------------------------------------------------
168 // Operations
169 // ------------------------------------------------------------------------
170
171 /**
172 * Creates one trace file reader per trace file contained in the trace.
db8e8f7d
AM
173 *
174 * @throws CTFReaderException
175 * if an error occurs
866e5b51 176 */
db8e8f7d 177 private void createStreamInputReaders() throws CTFReaderException {
866e5b51
FC
178 /*
179 * For each stream.
180 */
93a45b54 181 for (Stream stream : fTrace.getStreams()) {
866e5b51
FC
182 Set<StreamInput> streamInputs = stream.getStreamInputs();
183
184 /*
185 * For each trace file of the stream.
186 */
187 for (StreamInput streamInput : streamInputs) {
188 /*
189 * Create a reader.
190 */
191 StreamInputReader streamInputReader = new StreamInputReader(
192 streamInput);
193
194 /*
195 * Add it to the group.
196 */
93a45b54 197 fStreamInputReaders.add(streamInputReader);
866e5b51
FC
198 }
199 }
200
201 /*
202 * Create the array to count the number of event per trace file.
203 */
93a45b54 204 fEventCountPerTraceFile = new long[fStreamInputReaders.size()];
866e5b51
FC
205 }
206
207 /**
208 * Initializes the priority queue used to choose the trace file with the
209 * lower next event timestamp.
db8e8f7d
AM
210 *
211 * @throws CTFReaderException
212 * if an error occurs
866e5b51 213 */
db8e8f7d 214 private void populateStreamInputReaderHeap() throws CTFReaderException {
93a45b54
MK
215 if (fStreamInputReaders.isEmpty()) {
216 fPrio = new PriorityQueue<>();
b5354daa
MAL
217 return;
218 }
219
866e5b51
FC
220 /*
221 * Create the priority queue with a size twice as bigger as the number
222 * of reader in order to avoid constant resizing.
223 */
93a45b54
MK
224 fPrio = new PriorityQueue<>(
225 fStreamInputReaders.size() * 2,
866e5b51
FC
226 new StreamInputReaderTimestampComparator());
227
228 int pos = 0;
229
93a45b54 230 for (StreamInputReader reader : fStreamInputReaders) {
866e5b51
FC
231 /*
232 * Add each trace file reader in the priority queue, if we are able
233 * to read an event from it.
234 */
bfe038ff 235 reader.setParent(this);
866e5b51 236 if (reader.readNextEvent()) {
93a45b54 237 fPrio.add(reader);
866e5b51 238
93a45b54 239 fEventCountPerTraceFile[pos] = 0;
866e5b51
FC
240 reader.setName(pos);
241
242 pos++;
243 }
244 }
245 }
246
247 /**
248 * Get the current event, which is the current event of the trace file
249 * reader with the lowest timestamp.
250 *
251 * @return An event definition, or null of the trace reader reached the end
252 * of the trace.
253 */
254 public EventDefinition getCurrentEventDef() {
ce2388e0 255 StreamInputReader top = getTopStream();
866e5b51
FC
256
257 return (top != null) ? top.getCurrentEvent() : null;
258 }
259
260 /**
261 * Go to the next event.
262 *
263 * @return True if an event was read.
db8e8f7d
AM
264 * @throws CTFReaderException
265 * if an error occurs
866e5b51 266 */
db8e8f7d 267 public boolean advance() throws CTFReaderException {
866e5b51
FC
268 /*
269 * Remove the reader from the top of the priority queue.
270 */
93a45b54 271 StreamInputReader top = fPrio.poll();
866e5b51
FC
272
273 /*
274 * If the queue was empty.
275 */
276 if (top == null) {
277 return false;
278 }
866e5b51
FC
279 /*
280 * Read the next event of this reader.
281 */
282 if (top.readNextEvent()) {
283 /*
284 * Add it back in the queue.
285 */
93a45b54
MK
286 fPrio.add(top);
287 final long topEnd = fTrace.timestampCyclesToNanos(top.getCurrentEvent().getTimestamp());
288 setEndTime(Math.max(topEnd, getEndTime()));
289 fEventCountPerTraceFile[top.getName()]++;
866e5b51 290
bfe038ff 291 if (top.getCurrentEvent() != null) {
93a45b54
MK
292 fEndTime = Math.max(top.getCurrentEvent().getTimestamp(),
293 fEndTime);
bfe038ff
MK
294 }
295 }
866e5b51
FC
296 /*
297 * If there is no reader in the queue, it means the trace reader reached
298 * the end of the trace.
299 */
bfe038ff 300 return hasMoreEvents();
866e5b51
FC
301 }
302
303 /**
304 * Go to the last event in the trace.
db8e8f7d
AM
305 *
306 * @throws CTFReaderException
307 * if an error occurs
866e5b51 308 */
db8e8f7d 309 public void goToLastEvent() throws CTFReaderException {
93a45b54
MK
310 seek(getEndTime());
311 while (fPrio.size() > 1) {
312 advance();
866e5b51
FC
313 }
314 }
315
316 /**
ecb12461
EB
317 * Seeks to a given timestamp. It will seek to the nearest event greater or
318 * equal to timestamp. If a trace is [10 20 30 40] and you are looking for
319 * 19, it will give you 20. If you want 20, you will get 20, if you want 21,
320 * you will get 30. The value -inf will seek to the first element and the
321 * value +inf will seek to the end of the file (past the last event).
866e5b51
FC
322 *
323 * @param timestamp
324 * the timestamp to seek to
ecb12461
EB
325 * @return true if there are events above or equal the seek timestamp,
326 * false if seek at the end of the trace (no valid event).
db8e8f7d
AM
327 * @throws CTFReaderException
328 * if an error occurs
866e5b51 329 */
db8e8f7d 330 public boolean seek(long timestamp) throws CTFReaderException {
866e5b51
FC
331 /*
332 * Remove all the trace readers from the priority queue
333 */
93a45b54
MK
334 fPrio.clear();
335 for (StreamInputReader streamInputReader : fStreamInputReaders) {
866e5b51
FC
336 /*
337 * Seek the trace reader.
338 */
bfe038ff 339 streamInputReader.seek(timestamp);
ce2388e0
FC
340
341 /*
342 * Add it to the priority queue if there is a current event.
343 */
ce2388e0 344 if (streamInputReader.getCurrentEvent() != null) {
93a45b54 345 fPrio.add(streamInputReader);
ce2388e0
FC
346 }
347 }
866e5b51
FC
348 return hasMoreEvents();
349 }
350
9ac2eb62 351 /**
ecb12461 352 * Gets the stream with the oldest event
9ac2eb62
MK
353 *
354 * @return the stream with the oldest event
355 */
ce2388e0 356 public StreamInputReader getTopStream() {
93a45b54 357 return fPrio.peek();
ce2388e0
FC
358 }
359
866e5b51
FC
360 /**
361 * Does the trace have more events?
362 *
363 * @return true if yes.
364 */
0594c61c 365 public final boolean hasMoreEvents() {
93a45b54 366 return fPrio.size() > 0;
866e5b51
FC
367 }
368
369 /**
370 * Prints the event count stats.
371 */
372 public void printStats() {
373 printStats(60);
374 }
375
376 /**
377 * Prints the event count stats.
378 *
379 * @param width
380 * Width of the display.
381 */
382 public void printStats(int width) {
383 int numEvents = 0;
384 if (width == 0) {
385 return;
386 }
387
93a45b54 388 for (long i : fEventCountPerTraceFile) {
866e5b51
FC
389 numEvents += i;
390 }
391
93a45b54
MK
392 for (int j = 0; j < fEventCountPerTraceFile.length; j++) {
393 StreamInputReader se = fStreamInputReaders.get(j);
866e5b51 394
93a45b54 395 long len = (width * fEventCountPerTraceFile[se.getName()])
866e5b51
FC
396 / numEvents;
397
0594c61c
AM
398 StringBuilder sb = new StringBuilder(se.getFilename());
399 sb.append("\t["); //$NON-NLS-1$
866e5b51
FC
400
401 for (int i = 0; i < len; i++) {
402 sb.append('+');
403 }
404
bfe038ff 405 for (long i = len; i < width; i++) {
866e5b51
FC
406 sb.append(' ');
407 }
408
93a45b54 409 sb.append("]\t" + fEventCountPerTraceFile[se.getName()] + " Events"); //$NON-NLS-1$//$NON-NLS-2$
4311ac8b 410 Activator.log(sb.toString());
866e5b51
FC
411 }
412 }
413
9ac2eb62 414 /**
ecb12461 415 * Gets the last event timestamp that was read. This is NOT necessarily the
9ac2eb62
MK
416 * last event in a trace, just the last one read so far.
417 *
418 * @return the last event
419 */
866e5b51 420 public long getEndTime() {
93a45b54 421 return fEndTime;
866e5b51
FC
422 }
423
424 @Override
425 public int hashCode() {
426 final int prime = 31;
427 int result = 1;
93a45b54
MK
428 result = (prime * result) + (int) (fStartTime ^ (fStartTime >>> 32));
429 result = (prime * result) + fStreamInputReaders.hashCode();
430 result = (prime * result) + ((fTrace == null) ? 0 : fTrace.hashCode());
866e5b51
FC
431 return result;
432 }
433
434 @Override
435 public boolean equals(Object obj) {
436 if (this == obj) {
437 return true;
438 }
439 if (obj == null) {
440 return false;
441 }
07002e0a 442 if (!(obj instanceof CTFTraceReader)) {
866e5b51
FC
443 return false;
444 }
445 CTFTraceReader other = (CTFTraceReader) obj;
93a45b54 446 if (!fStreamInputReaders.equals(other.fStreamInputReaders)) {
866e5b51
FC
447 return false;
448 }
93a45b54
MK
449 if (fTrace == null) {
450 if (other.fTrace != null) {
866e5b51
FC
451 return false;
452 }
93a45b54 453 } else if (!fTrace.equals(other.fTrace)) {
866e5b51
FC
454 return false;
455 }
456 return true;
457 }
458
866e5b51
FC
459 @Override
460 public String toString() {
461 /* Only for debugging, shouldn't be externalized */
93a45b54 462 return "CTFTraceReader [trace=" + fTrace + ']'; //$NON-NLS-1$
866e5b51
FC
463 }
464
9ac2eb62
MK
465 /**
466 * Gets the parent trace
467 *
468 * @return the parent trace
469 */
866e5b51 470 public CTFTrace getTrace() {
93a45b54 471 return fTrace;
866e5b51
FC
472 }
473}
This page took 0.065796 seconds and 5 git commands to generate.