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