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