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