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