ctf: Add missing @since to previous patch
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFTraceReader.java
CommitLineData
866e5b51 1/*******************************************************************************
4bd7f2db 2 * Copyright (c) 2011, 2013 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 */
41 private final CTFTrace trace;
42
43 /**
44 * Vector of all the trace file readers.
45 */
0594c61c 46 private final List<StreamInputReader> streamInputReaders = new ArrayList<StreamInputReader>();
866e5b51
FC
47
48 /**
49 * Priority queue to order the trace file readers by timestamp.
50 */
0594c61c 51 private PriorityQueue<StreamInputReader> prio;
866e5b51
FC
52
53 /**
54 * Array to count the number of event per trace file.
55 */
bfe038ff 56 private long[] eventCountPerTraceFile;
866e5b51
FC
57
58 /**
59 * Timestamp of the first event in the trace
60 */
61 private long startTime;
62
63 /**
64 * Timestamp of the last event read so far
65 */
66 private long endTime;
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 {
866e5b51 81 this.trace = trace;
bfe038ff 82 streamInputReaders.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 */
0594c61c 98 this.startTime = 0;
33656d8e 99 if (hasMoreEvents()) {
aa572e22 100 this.startTime = prio.peek().getCurrentEvent().getTimestamp();
1191a574 101 this.setEndTime(this.startTime);
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
114 newReader = new CTFTraceReader(this.trace);
115 newReader.startTime = this.startTime;
1191a574 116 newReader.setEndTime(this.endTime);
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() {
126 for (StreamInputReader reader : streamInputReaders) {
127 if (reader != null) {
128 reader.dispose();
129 }
130 }
131 streamInputReaders.clear();
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() {
144 return this.startTime;
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) {
6f4e8ec0
AM
154 this.endTime = endTime;
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() {
164 return prio;
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 */
f7c5789a 181 for (Stream stream : this.trace.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 */
197 this.streamInputReaders.add(streamInputReader);
198 }
199 }
200
201 /*
202 * Create the array to count the number of event per trace file.
203 */
bfe038ff 204 this.eventCountPerTraceFile = new long[this.streamInputReaders.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 {
b5354daa
MAL
215 if (this.streamInputReaders.isEmpty()) {
216 this.prio = new PriorityQueue<StreamInputReader>();
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 */
224 this.prio = new PriorityQueue<StreamInputReader>(
225 this.streamInputReaders.size() * 2,
226 new StreamInputReaderTimestampComparator());
227
228 int pos = 0;
229
230 for (StreamInputReader reader : this.streamInputReaders) {
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
FC
236 if (reader.readNextEvent()) {
237 this.prio.add(reader);
238
239 this.eventCountPerTraceFile[pos] = 0;
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 */
271 StreamInputReader top = this.prio.poll();
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 */
286 this.prio.add(top);
1d7277f3 287 final long topEnd = this.trace.timestampCyclesToNanos(top.getCurrentEvent().getTimestamp());
9ac2eb62 288 this.setEndTime(Math.max(topEnd, this.getEndTime()));
866e5b51 289 this.eventCountPerTraceFile[top.getName()]++;
866e5b51 290
bfe038ff
MK
291 if (top.getCurrentEvent() != null) {
292 this.endTime = Math.max(top.getCurrentEvent().getTimestamp(),
293 this.endTime);
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 {
bfe038ff
MK
310 seek(this.getEndTime());
311 while (this.prio.size() > 1) {
312 this.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 */
334 this.prio.clear();
866e5b51
FC
335 for (StreamInputReader streamInputReader : this.streamInputReaders) {
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
FC
344 if (streamInputReader.getCurrentEvent() != null) {
345 this.prio.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
FC
356 public StreamInputReader getTopStream() {
357 return this.prio.peek();
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() {
866e5b51
FC
366 return this.prio.size() > 0;
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
bfe038ff 388 for (long i : this.eventCountPerTraceFile) {
866e5b51
FC
389 numEvents += i;
390 }
391
392 for (int j = 0; j < this.eventCountPerTraceFile.length; j++) {
393 StreamInputReader se = this.streamInputReaders.get(j);
394
bfe038ff 395 long len = (width * this.eventCountPerTraceFile[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
409 sb.append("]\t" + this.eventCountPerTraceFile[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
FC
420 public long getEndTime() {
421 return this.endTime;
422 }
423
424 @Override
425 public int hashCode() {
426 final int prime = 31;
427 int result = 1;
866e5b51 428 result = (prime * result) + (int) (startTime ^ (startTime >>> 32));
77fdc5df 429 result = (prime * result) + streamInputReaders.hashCode();
866e5b51
FC
430 result = (prime * result) + ((trace == null) ? 0 : trace.hashCode());
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;
77fdc5df 446 if (!streamInputReaders.equals(other.streamInputReaders)) {
866e5b51
FC
447 return false;
448 }
449 if (trace == null) {
450 if (other.trace != null) {
451 return false;
452 }
453 } else if (!trace.equals(other.trace)) {
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 */
462 return "CTFTraceReader [trace=" + trace + ']'; //$NON-NLS-1$
463 }
464
9ac2eb62
MK
465 /**
466 * Gets the parent trace
467 *
468 * @return the parent trace
469 */
866e5b51
FC
470 public CTFTrace getTrace() {
471 return trace;
472 }
473}
This page took 0.057495 seconds and 5 git commands to generate.