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