Fix endless loop in Resources view when trace is disposed
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputReader.java
CommitLineData
866e5b51
FC
1/*******************************************************************************
2 * Copyright (c) 2011-2012 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
13package org.eclipse.linuxtools.ctf.core.trace;
14
ce2388e0 15import java.nio.ByteOrder;
866e5b51
FC
16
17import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
18import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
ce2388e0 19import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51
FC
20
21/**
d37aaa7f 22 * A CTF trace event reader. Reads the events of a trace file.
32ede2ec 23 *
d37aaa7f
FC
24 * @version 1.0
25 * @author Matthew Khouzam
26 * @author Simon Marchi
866e5b51
FC
27 */
28public class StreamInputReader {
29
30 // ------------------------------------------------------------------------
31 // Attributes
32 // ------------------------------------------------------------------------
33
34 /**
35 * The StreamInput we are reading.
36 */
37 private final StreamInput streamInput;
38
39 /**
40 * The packet reader used to read packets from this trace file.
41 */
42 private final StreamInputPacketReader packetReader;
43
44 /**
45 * Iterator on the packet index
46 */
bfe038ff 47 private int packetIndex;
866e5b51
FC
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 currentEvent = null;
54
55 private int name;
56
bfe038ff
MK
57 private CTFTraceReader parent;
58
bfe038ff 59
866e5b51
FC
60 // ------------------------------------------------------------------------
61 // Constructors
62 // ------------------------------------------------------------------------
63
64 /**
65 * Constructs a StreamInputReader that reads a StreamInput.
66 *
67 * @param streamInput
68 * The StreamInput to read.
69 */
70 public StreamInputReader(StreamInput streamInput) {
71 this.streamInput = streamInput;
72 this.packetReader = new StreamInputPacketReader(this);
866e5b51
FC
73 /*
74 * Get the iterator on the packet index.
75 */
bfe038ff 76 this.packetIndex = 0;
866e5b51
FC
77 /*
78 * Make first packet the current one.
79 */
80 goToNextPacket();
81 }
82
83 // ------------------------------------------------------------------------
84 // Getters/Setters/Predicates
85 // ------------------------------------------------------------------------
86
9ac2eb62
MK
87 /**
88 * Gets the current event in this stream
89 *
90 * @return the current event in the stream, null if the stream is
91 * finished/empty/malformed
92 */
866e5b51
FC
93 public EventDefinition getCurrentEvent() {
94 return this.currentEvent;
95 }
96
9ac2eb62
MK
97 /**
98 * gets the current packet context
99 *
100 * @return the current packet context (size, lost events and such)
101 */
866e5b51
FC
102 public StructDefinition getCurrentPacketContext() {
103 return this.packetReader.getStreamPacketContextDef();
104 }
105
9ac2eb62
MK
106 /**
107 * Gets the byte order for a trace
108 *
109 * @return the trace byte order
110 */
ce2388e0
FC
111 public ByteOrder getByteOrder() {
112 return streamInput.getStream().getTrace().getByteOrder();
866e5b51
FC
113 }
114
9ac2eb62
MK
115 /**
116 * Gets the name of the stream (it's an id and a number)
117 *
118 * @return gets the stream name (it's a number)
119 */
866e5b51
FC
120 public int getName() {
121 return this.name;
122 }
123
9ac2eb62
MK
124 /**
125 * Sets the name of the stream
126 *
127 * @param name
128 * the name of the stream, (it's a number)
129 */
866e5b51
FC
130 public void setName(int name) {
131 this.name = name;
132 }
133
9ac2eb62
MK
134 /**
135 * Gets the CPU of a stream. It's the same as the one in /proc or running
136 * the asm CPUID instruction
137 *
138 * @return The CPU id (a number)
139 */
866e5b51
FC
140 public int getCPU() {
141 return this.packetReader.getCPU();
142 }
143
9ac2eb62
MK
144 /**
145 * Gets the filename of the stream being read
146 * @return The filename of the stream being read
147 */
ce2388e0
FC
148 public String getFilename() {
149 return streamInput.getFilename();
150 }
151
152 /*
153 * for internal use only
154 */
155 StreamInput getStreamInput() {
156 return streamInput;
157 }
158
866e5b51
FC
159 // ------------------------------------------------------------------------
160 // Operations
161 // ------------------------------------------------------------------------
162 /**
163 * Reads the next event in the current event variable.
164 *
165 * @return If an event has been successfully read.
166 */
167 public boolean readNextEvent() {
bfe038ff 168
866e5b51
FC
169 /*
170 * Change packet if needed
171 */
172 if (!this.packetReader.hasMoreEvents()) {
bfe038ff
MK
173 final StreamInputPacketIndexEntry prevPacket = this.packetReader
174 .getCurrentPacket();
175 if (prevPacket != null) {
176 goToNextPacket();
bfe038ff 177 }
866e5b51
FC
178 }
179
32ede2ec 180 /*
866e5b51
FC
181 * If an event is available, read it.
182 */
183 if (this.packetReader.hasMoreEvents()) {
184 try {
185 this.setCurrentEvent(this.packetReader.readNextEvent());
186 } catch (CTFReaderException e) {
bfe038ff
MK
187 /*
188 * Some problem happened, we'll assume that there are no more
189 * events
190 */
866e5b51
FC
191 return false;
192 }
193 return true;
194 }
195 this.setCurrentEvent(null);
196 return false;
197 }
198
199 /**
200 * Change the current packet of the packet reader to the next one.
201 */
202 private void goToNextPacket() {
bfe038ff
MK
203 packetIndex++;
204 if (getPacketSize() >= (packetIndex + 1)) {
205 this.packetReader.setCurrentPacket(getPacket());
866e5b51 206 } else {
bfe038ff
MK
207 try {
208 if (this.streamInput.addPacketHeaderIndex()) {
209 packetIndex = getPacketSize() - 1;
210 this.packetReader.setCurrentPacket(getPacket());
211
212 } else {
213 this.packetReader.setCurrentPacket(null);
214 }
215
216 } catch (CTFReaderException e) {
217 this.packetReader.setCurrentPacket(null);
218 }
866e5b51
FC
219 }
220 }
221
bfe038ff
MK
222 /**
223 * @return
224 */
225 private int getPacketSize() {
226 return streamInput.getIndex().getEntries().size();
227 }
228
866e5b51
FC
229 /**
230 * Changes the location of the trace file reader so that the current event
231 * is the first event with a timestamp greater than the given timestamp.
232 *
233 * @param timestamp
234 * The timestamp to seek to.
be6df2d8 235 * @return The offset compared to the current position
866e5b51 236 */
ce2388e0
FC
237 public long seek(long timestamp) {
238 long offset = 0;
866e5b51 239
eb94f9c9 240 gotoPacket(timestamp);
866e5b51 241
0c59c1a6
MK
242 /*
243 * index up to the desired timestamp.
244 */
245 while ((this.packetReader.getCurrentPacket() != null)
246 && (this.packetReader.getCurrentPacket().getTimestampEnd() < timestamp)) {
247 try {
248 this.streamInput.addPacketHeaderIndex();
249 goToNextPacket();
250 } catch (CTFReaderException e) {
251 // do nothing here
252 }
253 }
9ac2eb62 254 if (this.packetReader.getCurrentPacket() == null) {
eb94f9c9
MK
255 gotoPacket(timestamp);
256 }
0c59c1a6 257
866e5b51
FC
258 /*
259 * Advance until A. we reached the end of the trace file (which means
260 * the given timestamp is after the last event), or B. we found the
261 * first event with a timestamp greater than the given timestamp.
262 */
263 readNextEvent();
264 boolean done = (this.getCurrentEvent() == null);
aa572e22 265 while (!done && (this.getCurrentEvent().getTimestamp() < timestamp)) {
866e5b51
FC
266 readNextEvent();
267 done = (this.getCurrentEvent() == null);
ce2388e0 268 offset++;
866e5b51 269 }
ce2388e0
FC
270 return offset;
271 }
272
eb94f9c9
MK
273 /**
274 * @param timestamp
275 */
276 private void gotoPacket(long timestamp) {
277 this.packetIndex = this.streamInput.getIndex().search(timestamp)
278 .previousIndex();
279 /*
280 * Switch to this packet.
281 */
282 goToNextPacket();
283 }
284
9ac2eb62
MK
285 /**
286 * Seeks the last event of a stream and returns it.
287 */
bfe038ff 288 public void goToLastEvent() {
866e5b51
FC
289 /*
290 * Search in the index for the packet to search in.
291 */
ec6f5beb
MK
292 final int len = this.streamInput.getIndex().getEntries().size();
293
aa3b05ef
FC
294 @SuppressWarnings("unused")
295 StreamInputPacketIndexEntry entry = null;
866e5b51 296 /*
ec6f5beb 297 * Go to beginning of trace.
866e5b51 298 */
ec6f5beb
MK
299 seek(0);
300 /*
301 * if the trace is empty.
302 */
bfe038ff 303 if ((len == 0) || (this.packetReader.hasMoreEvents() == false)) {
ec6f5beb
MK
304 /*
305 * This means the trace is empty. abort.
306 */
307 return;
ce2388e0 308 }
ec6f5beb
MK
309 /*
310 * Go to the last packet that contains events.
311 */
bfe038ff
MK
312 for (int pos = len - 1; pos > 0; pos--) {
313 packetIndex = pos;
314 this.packetReader.setCurrentPacket(getPacket());
315 if (this.packetReader.hasMoreEvents()) {
ec6f5beb
MK
316 break;
317 }
866e5b51 318 }
ec6f5beb
MK
319
320 /*
321 * Go until the end of that packet
322 */
323 EventDefinition prevEvent = null;
324 while (this.currentEvent != null) {
325 prevEvent = this.currentEvent;
326 this.readNextEvent();
327 }
328 /*
329 * Go back to the previous event
330 */
331 this.setCurrentEvent(prevEvent);
866e5b51
FC
332 }
333
bfe038ff
MK
334 /**
335 * @return the parent
336 */
337 public CTFTraceReader getParent() {
338 return parent;
339 }
340
341 /**
342 * @param parent
343 * the parent to set
344 */
345 public void setParent(CTFTraceReader parent) {
346 this.parent = parent;
347 }
348
9ac2eb62
MK
349 /**
350 * Sets the current event in a stream input reader
351 * @param currentEvent the event to set
352 */
866e5b51
FC
353 public void setCurrentEvent(EventDefinition currentEvent) {
354 this.currentEvent = currentEvent;
355 }
356
ce2388e0
FC
357 /**
358 * @return the packetIndexIt
359 */
bfe038ff
MK
360 private int getPacketIndex() {
361 return packetIndex;
362 }
363
364 private StreamInputPacketIndexEntry getPacket() {
365 return streamInput.getIndex().getEntries().get(getPacketIndex());
ce2388e0
FC
366 }
367
368 /**
369 * @return the packetReader
370 */
371 public StreamInputPacketReader getPacketReader() {
372 return packetReader;
373 }
374
bfe038ff
MK
375 /*
376 * (non-Javadoc)
377 *
81c8e6f7
MK
378 * @see java.lang.Object#hashCode()
379 */
380 @Override
381 public int hashCode() {
382 final int prime = 31;
383 int result = 1;
384 result = (prime * result) + name;
385 result = (prime * result)
386 + ((streamInput == null) ? 0 : streamInput.hashCode());
387 return result;
388 }
389
bfe038ff
MK
390 /*
391 * (non-Javadoc)
392 *
81c8e6f7
MK
393 * @see java.lang.Object#equals(java.lang.Object)
394 */
395 @Override
396 public boolean equals(Object obj) {
397 if (this == obj) {
398 return true;
399 }
400 if (obj == null) {
401 return false;
402 }
403 if (!(obj instanceof StreamInputReader)) {
404 return false;
405 }
406 StreamInputReader other = (StreamInputReader) obj;
407 if (name != other.name) {
408 return false;
409 }
410 if (streamInput == null) {
411 if (other.streamInput != null) {
412 return false;
413 }
414 } else if (!streamInput.equals(other.streamInput)) {
415 return false;
416 }
417 return true;
418 }
419
866e5b51 420}
This page took 0.048889 seconds and 5 git commands to generate.