ctf: make StreamInputPacketIndex more list like
[deliverable/tracecompass.git] / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / trace / CTFStreamInputReader.java
CommitLineData
866e5b51 1/*******************************************************************************
60ae41e1 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 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12
f357bcd4 13package org.eclipse.tracecompass.ctf.core.trace;
866e5b51 14
b3151232
MK
15import java.io.File;
16import java.io.IOException;
ce2388e0 17import java.nio.ByteOrder;
b3151232
MK
18import java.nio.channels.FileChannel;
19import java.nio.file.StandardOpenOption;
866e5b51 20
70f60307 21import org.eclipse.jdt.annotation.NonNull;
f357bcd4
AM
22import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
23import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
24import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
25import org.eclipse.tracecompass.internal.ctf.core.Activator;
26import org.eclipse.tracecompass.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51 27
5f715709 28import com.google.common.collect.ImmutableList;
53359017 29
866e5b51 30/**
d37aaa7f 31 * A CTF trace event reader. Reads the events of a trace file.
32ede2ec 32 *
d37aaa7f
FC
33 * @author Matthew Khouzam
34 * @author Simon Marchi
d84419e1 35 * @since 3.0
866e5b51 36 */
d84419e1 37public class CTFStreamInputReader implements AutoCloseable {
866e5b51
FC
38
39 // ------------------------------------------------------------------------
40 // Attributes
41 // ------------------------------------------------------------------------
42
43 /**
44 * The StreamInput we are reading.
45 */
b3151232
MK
46 private final @NonNull File fFile;
47
70f60307 48 private final @NonNull CTFStreamInput fStreamInput;
866e5b51 49
b3151232
MK
50 private final FileChannel fFileChannel;
51
866e5b51
FC
52 /**
53 * The packet reader used to read packets from this trace file.
54 */
d84419e1 55 private final CTFStreamInputPacketReader fPacketReader;
866e5b51
FC
56
57 /**
58 * Iterator on the packet index
59 */
93a45b54 60 private int fPacketIndex;
866e5b51
FC
61
62 /**
63 * Reference to the current event of this trace file (iow, the last on that
64 * was read, the next one to be returned)
65 */
93a45b54 66 private EventDefinition fCurrentEvent = null;
866e5b51 67
93a45b54 68 private int fId;
866e5b51 69
93a45b54 70 private CTFTraceReader fParent;
bfe038ff 71
6a5251eb
MK
72 /**
73 * Live trace reading
74 */
75 private boolean fLive = false;
76
866e5b51
FC
77 // ------------------------------------------------------------------------
78 // Constructors
79 // ------------------------------------------------------------------------
866e5b51
FC
80 /**
81 * Constructs a StreamInputReader that reads a StreamInput.
82 *
83 * @param streamInput
84 * The StreamInput to read.
db8e8f7d 85 * @throws CTFReaderException
b3151232 86 * If the file cannot be opened
866e5b51 87 */
d84419e1 88 public CTFStreamInputReader(CTFStreamInput streamInput) throws CTFReaderException {
70f60307 89 if (streamInput == null) {
b3151232 90 throw new IllegalArgumentException("stream cannot be null"); //$NON-NLS-1$
70f60307 91 }
93a45b54 92 fStreamInput = streamInput;
b3151232
MK
93 fFile = fStreamInput.getFile();
94 try {
95 fFileChannel = FileChannel.open(fFile.toPath(), StandardOpenOption.READ);
96 } catch (IOException e) {
97 throw new CTFReaderException(e);
98 }
d84419e1 99 fPacketReader = new CTFStreamInputPacketReader(this);
866e5b51
FC
100 /*
101 * Get the iterator on the packet index.
102 */
93a45b54 103 fPacketIndex = 0;
866e5b51
FC
104 /*
105 * Make first packet the current one.
106 */
107 goToNextPacket();
108 }
109
5d1c6919 110 /**
b3151232
MK
111 * Dispose the StreamInputReader, closes the file channel and its packet
112 * reader
113 *
114 * @throws IOException
115 * If an I/O error occurs
5d1c6919 116 */
dd9752d5 117 @Override
b3151232
MK
118 public void close() throws IOException {
119 fFileChannel.close();
dd9752d5 120 fPacketReader.close();
5d1c6919
PT
121 }
122
866e5b51
FC
123 // ------------------------------------------------------------------------
124 // Getters/Setters/Predicates
125 // ------------------------------------------------------------------------
126
9ac2eb62
MK
127 /**
128 * Gets the current event in this stream
129 *
130 * @return the current event in the stream, null if the stream is
131 * finished/empty/malformed
132 */
866e5b51 133 public EventDefinition getCurrentEvent() {
93a45b54 134 return fCurrentEvent;
866e5b51
FC
135 }
136
9ac2eb62
MK
137 /**
138 * Gets the byte order for a trace
139 *
140 * @return the trace byte order
141 */
ce2388e0 142 public ByteOrder getByteOrder() {
93a45b54 143 return fStreamInput.getStream().getTrace().getByteOrder();
866e5b51
FC
144 }
145
9ac2eb62
MK
146 /**
147 * Gets the name of the stream (it's an id and a number)
148 *
149 * @return gets the stream name (it's a number)
150 */
866e5b51 151 public int getName() {
93a45b54 152 return fId;
866e5b51
FC
153 }
154
9ac2eb62
MK
155 /**
156 * Sets the name of the stream
157 *
158 * @param name
159 * the name of the stream, (it's a number)
160 */
866e5b51 161 public void setName(int name) {
93a45b54 162 fId = name;
866e5b51
FC
163 }
164
9ac2eb62
MK
165 /**
166 * Gets the CPU of a stream. It's the same as the one in /proc or running
167 * the asm CPUID instruction
168 *
169 * @return The CPU id (a number)
170 */
866e5b51 171 public int getCPU() {
93a45b54 172 return fPacketReader.getCPU();
866e5b51
FC
173 }
174
9ac2eb62
MK
175 /**
176 * Gets the filename of the stream being read
db8e8f7d 177 *
9ac2eb62
MK
178 * @return The filename of the stream being read
179 */
ce2388e0 180 public String getFilename() {
93a45b54 181 return fStreamInput.getFilename();
ce2388e0
FC
182 }
183
184 /*
185 * for internal use only
186 */
d84419e1 187 CTFStreamInput getStreamInput() {
93a45b54 188 return fStreamInput;
ce2388e0
FC
189 }
190
53359017
MK
191 /**
192 * Gets the event definition set for this StreamInput
193 *
194 * @return Unmodifiable set with the event definitions
53359017
MK
195 */
196 public Iterable<IEventDeclaration> getEventDeclarations() {
5f715709 197 return ImmutableList.copyOf(fStreamInput.getStream().getEventDeclarations());
53359017
MK
198 }
199
6a5251eb
MK
200 /**
201 * Set the trace to live mode
202 *
203 * @param live
204 * whether the trace is read live or not
6a5251eb
MK
205 */
206 public void setLive(boolean live) {
207 fLive = live;
208 }
209
210 /**
211 * Get if the trace is to read live or not
212 *
213 * @return whether the trace is live or not
6a5251eb
MK
214 */
215 public boolean isLive() {
216 return fLive;
217 }
218
a4fa4e36
MK
219 /**
220 * Get the event context of the stream
221 *
222 * @return the event context declaration of the stream
a4fa4e36
MK
223 */
224 public StructDeclaration getStreamEventContextDecl() {
225 return getStreamInput().getStream().getEventContextDecl();
226 }
227
866e5b51
FC
228 // ------------------------------------------------------------------------
229 // Operations
230 // ------------------------------------------------------------------------
231 /**
232 * Reads the next event in the current event variable.
233 *
234 * @return If an event has been successfully read.
db8e8f7d
AM
235 * @throws CTFReaderException
236 * if an error occurs
866e5b51 237 */
6a5251eb 238 public CTFResponse readNextEvent() throws CTFReaderException {
bfe038ff 239
866e5b51
FC
240 /*
241 * Change packet if needed
242 */
93a45b54
MK
243 if (!fPacketReader.hasMoreEvents()) {
244 final StreamInputPacketIndexEntry prevPacket = fPacketReader
bfe038ff 245 .getCurrentPacket();
a4fa4e36 246 if (prevPacket != null || fLive) {
bfe038ff 247 goToNextPacket();
bfe038ff 248 }
6a5251eb 249
866e5b51
FC
250 }
251
32ede2ec 252 /*
866e5b51
FC
253 * If an event is available, read it.
254 */
93a45b54 255 if (fPacketReader.hasMoreEvents()) {
6a5251eb
MK
256 setCurrentEvent(fPacketReader.readNextEvent());
257 return CTFResponse.OK;
866e5b51
FC
258 }
259 this.setCurrentEvent(null);
6a5251eb 260 return fLive ? CTFResponse.WAIT : CTFResponse.FINISH;
866e5b51
FC
261 }
262
263 /**
264 * Change the current packet of the packet reader to the next one.
db8e8f7d
AM
265 *
266 * @throws CTFReaderException
267 * if an error occurs
866e5b51 268 */
db8e8f7d 269 private void goToNextPacket() throws CTFReaderException {
93a45b54 270 fPacketIndex++;
6a5251eb 271 // did we already index the packet?
93a45b54
MK
272 if (getPacketSize() >= (fPacketIndex + 1)) {
273 fPacketReader.setCurrentPacket(getPacket());
866e5b51 274 } else {
6a5251eb 275 // go to the next packet if there is one, index it at the same time
93a45b54
MK
276 if (fStreamInput.addPacketHeaderIndex()) {
277 fPacketIndex = getPacketSize() - 1;
278 fPacketReader.setCurrentPacket(getPacket());
cf9a28da 279 } else {
6a5251eb 280 // out of packets
93a45b54 281 fPacketReader.setCurrentPacket(null);
bfe038ff 282 }
866e5b51
FC
283 }
284 }
285
bfe038ff
MK
286 /**
287 * @return
288 */
289 private int getPacketSize() {
3f02ac64 290 return fStreamInput.getIndex().size();
bfe038ff
MK
291 }
292
866e5b51
FC
293 /**
294 * Changes the location of the trace file reader so that the current event
ecb12461 295 * is the first event with a timestamp greater or equal the given timestamp.
866e5b51
FC
296 *
297 * @param timestamp
298 * The timestamp to seek to.
be6df2d8 299 * @return The offset compared to the current position
db8e8f7d
AM
300 * @throws CTFReaderException
301 * if an error occurs
866e5b51 302 */
db8e8f7d 303 public long seek(long timestamp) throws CTFReaderException {
ce2388e0 304 long offset = 0;
866e5b51 305
eb94f9c9 306 gotoPacket(timestamp);
866e5b51 307
0c59c1a6
MK
308 /*
309 * index up to the desired timestamp.
310 */
93a45b54
MK
311 while ((fPacketReader.getCurrentPacket() != null)
312 && (fPacketReader.getCurrentPacket().getTimestampEnd() < timestamp)) {
0c59c1a6 313 try {
93a45b54 314 fStreamInput.addPacketHeaderIndex();
0c59c1a6
MK
315 goToNextPacket();
316 } catch (CTFReaderException e) {
317 // do nothing here
b3151232 318 Activator.log(e.getMessage());
0c59c1a6
MK
319 }
320 }
93a45b54 321 if (fPacketReader.getCurrentPacket() == null) {
eb94f9c9
MK
322 gotoPacket(timestamp);
323 }
0c59c1a6 324
866e5b51 325 /*
6a5251eb
MK
326 * Advance until either of these conditions are met:
327 *
328 * - reached the end of the trace file (the given timestamp is after the
329 * last event)
330 *
331 * - found the first event with a timestamp greater or equal the given
332 * timestamp.
866e5b51
FC
333 */
334 readNextEvent();
335 boolean done = (this.getCurrentEvent() == null);
aa572e22 336 while (!done && (this.getCurrentEvent().getTimestamp() < timestamp)) {
866e5b51
FC
337 readNextEvent();
338 done = (this.getCurrentEvent() == null);
ce2388e0 339 offset++;
866e5b51 340 }
ce2388e0
FC
341 return offset;
342 }
343
eb94f9c9
MK
344 /**
345 * @param timestamp
6a5251eb 346 * the time to seek
db8e8f7d
AM
347 * @throws CTFReaderException
348 * if an error occurs
eb94f9c9 349 */
db8e8f7d 350 private void gotoPacket(long timestamp) throws CTFReaderException {
93a45b54 351 fPacketIndex = fStreamInput.getIndex().search(timestamp)
eb94f9c9
MK
352 .previousIndex();
353 /*
354 * Switch to this packet.
355 */
356 goToNextPacket();
357 }
358
9ac2eb62
MK
359 /**
360 * Seeks the last event of a stream and returns it.
db8e8f7d
AM
361 *
362 * @throws CTFReaderException
363 * if an error occurs
9ac2eb62 364 */
db8e8f7d 365 public void goToLastEvent() throws CTFReaderException {
866e5b51
FC
366 /*
367 * Search in the index for the packet to search in.
368 */
3f02ac64 369 final int len = fStreamInput.getIndex().size();
ec6f5beb 370
866e5b51 371 /*
ec6f5beb 372 * Go to beginning of trace.
866e5b51 373 */
ec6f5beb
MK
374 seek(0);
375 /*
376 * if the trace is empty.
377 */
3f02ac64 378 if ((fStreamInput.getIndex().isEmpty()) || (!fPacketReader.hasMoreEvents())) {
ec6f5beb
MK
379 /*
380 * This means the trace is empty. abort.
381 */
382 return;
ce2388e0 383 }
ec6f5beb
MK
384 /*
385 * Go to the last packet that contains events.
386 */
bfe038ff 387 for (int pos = len - 1; pos > 0; pos--) {
93a45b54
MK
388 fPacketIndex = pos;
389 fPacketReader.setCurrentPacket(getPacket());
390 if (fPacketReader.hasMoreEvents()) {
ec6f5beb
MK
391 break;
392 }
866e5b51 393 }
ec6f5beb
MK
394
395 /*
396 * Go until the end of that packet
397 */
398 EventDefinition prevEvent = null;
93a45b54
MK
399 while (fCurrentEvent != null) {
400 prevEvent = fCurrentEvent;
ec6f5beb
MK
401 this.readNextEvent();
402 }
403 /*
404 * Go back to the previous event
405 */
406 this.setCurrentEvent(prevEvent);
866e5b51
FC
407 }
408
bfe038ff
MK
409 /**
410 * @return the parent
411 */
412 public CTFTraceReader getParent() {
93a45b54 413 return fParent;
bfe038ff
MK
414 }
415
416 /**
417 * @param parent
418 * the parent to set
419 */
420 public void setParent(CTFTraceReader parent) {
93a45b54 421 fParent = parent;
bfe038ff
MK
422 }
423
9ac2eb62
MK
424 /**
425 * Sets the current event in a stream input reader
db8e8f7d
AM
426 *
427 * @param currentEvent
428 * the event to set
9ac2eb62 429 */
866e5b51 430 public void setCurrentEvent(EventDefinition currentEvent) {
93a45b54 431 fCurrentEvent = currentEvent;
866e5b51
FC
432 }
433
ce2388e0
FC
434 /**
435 * @return the packetIndexIt
436 */
bfe038ff 437 private int getPacketIndex() {
93a45b54 438 return fPacketIndex;
bfe038ff
MK
439 }
440
441 private StreamInputPacketIndexEntry getPacket() {
3f02ac64 442 return fStreamInput.getIndex().getElement(getPacketIndex());
ce2388e0
FC
443 }
444
b3151232
MK
445 /**
446 * Get the file channel wrapped by this reader
447 *
448 * @return the file channel
449 */
450 FileChannel getFc() {
451 return fFileChannel;
452 }
453
ce2388e0
FC
454 /**
455 * @return the packetReader
456 */
d84419e1 457 public CTFStreamInputPacketReader getPacketReader() {
93a45b54 458 return fPacketReader;
ce2388e0
FC
459 }
460
81c8e6f7
MK
461 @Override
462 public int hashCode() {
463 final int prime = 31;
464 int result = 1;
93a45b54 465 result = (prime * result) + fId;
81c8e6f7 466 result = (prime * result)
b3151232 467 + fFile.hashCode();
81c8e6f7
MK
468 return result;
469 }
470
81c8e6f7
MK
471 @Override
472 public boolean equals(Object obj) {
473 if (this == obj) {
474 return true;
475 }
476 if (obj == null) {
477 return false;
478 }
d84419e1 479 if (!(obj instanceof CTFStreamInputReader)) {
81c8e6f7
MK
480 return false;
481 }
d84419e1 482 CTFStreamInputReader other = (CTFStreamInputReader) obj;
93a45b54 483 if (fId != other.fId) {
81c8e6f7
MK
484 return false;
485 }
b3151232 486 return fFile.equals(other.fFile);
81c8e6f7
MK
487 }
488
87b60a47
MK
489 @Override
490 public String toString() {
491 // this helps debugging
93a45b54 492 return fId + ' ' + fCurrentEvent.toString();
87b60a47 493 }
b3151232 494
866e5b51 495}
This page took 0.087853 seconds and 5 git commands to generate.