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