ctf: replace HashMaps with ArrayLists for EventDeclaration storage
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFStreamInputReader.java
CommitLineData
866e5b51 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2011, 2014 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;
866e5b51 16
70f60307 17import org.eclipse.jdt.annotation.NonNull;
866e5b51 18import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
53359017 19import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
a4fa4e36 20import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
ce2388e0 21import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51 22
5f715709 23import com.google.common.collect.ImmutableList;
53359017 24
866e5b51 25/**
d37aaa7f 26 * A CTF trace event reader. Reads the events of a trace file.
32ede2ec 27 *
d37aaa7f
FC
28 * @author Matthew Khouzam
29 * @author Simon Marchi
d84419e1 30 * @since 3.0
866e5b51 31 */
d84419e1 32public class CTFStreamInputReader implements AutoCloseable {
866e5b51
FC
33
34 // ------------------------------------------------------------------------
35 // Attributes
36 // ------------------------------------------------------------------------
37
38 /**
39 * The StreamInput we are reading.
40 */
70f60307 41 private final @NonNull CTFStreamInput fStreamInput;
866e5b51
FC
42
43 /**
44 * The packet reader used to read packets from this trace file.
45 */
d84419e1 46 private final CTFStreamInputPacketReader fPacketReader;
866e5b51
FC
47
48 /**
49 * Iterator on the packet index
50 */
93a45b54 51 private int fPacketIndex;
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 */
93a45b54 57 private EventDefinition fCurrentEvent = null;
866e5b51 58
93a45b54 59 private int fId;
866e5b51 60
93a45b54 61 private CTFTraceReader fParent;
bfe038ff 62
6a5251eb
MK
63 /**
64 * Live trace reading
65 */
66 private boolean fLive = false;
67
866e5b51
FC
68 // ------------------------------------------------------------------------
69 // Constructors
70 // ------------------------------------------------------------------------
71
72 /**
73 * Constructs a StreamInputReader that reads a StreamInput.
74 *
75 * @param streamInput
76 * The StreamInput to read.
db8e8f7d
AM
77 * @throws CTFReaderException
78 * if an error occurs
866e5b51 79 */
d84419e1 80 public CTFStreamInputReader(CTFStreamInput streamInput) throws CTFReaderException {
70f60307
MK
81 if (streamInput == null) {
82 throw new IllegalArgumentException("streamInput cannot be null"); //$NON-NLS-1$
83 }
93a45b54 84 fStreamInput = streamInput;
d84419e1 85 fPacketReader = new CTFStreamInputPacketReader(this);
866e5b51
FC
86 /*
87 * Get the iterator on the packet index.
88 */
93a45b54 89 fPacketIndex = 0;
866e5b51
FC
90 /*
91 * Make first packet the current one.
92 */
93 goToNextPacket();
94 }
95
5d1c6919
PT
96 /**
97 * Dispose the StreamInputReader
5d1c6919 98 */
dd9752d5
AM
99 @Override
100 public void close() {
101 fPacketReader.close();
5d1c6919
PT
102 }
103
866e5b51
FC
104 // ------------------------------------------------------------------------
105 // Getters/Setters/Predicates
106 // ------------------------------------------------------------------------
107
9ac2eb62
MK
108 /**
109 * Gets the current event in this stream
110 *
111 * @return the current event in the stream, null if the stream is
112 * finished/empty/malformed
113 */
866e5b51 114 public EventDefinition getCurrentEvent() {
93a45b54 115 return fCurrentEvent;
866e5b51
FC
116 }
117
9ac2eb62
MK
118 /**
119 * Gets the byte order for a trace
120 *
121 * @return the trace byte order
122 */
ce2388e0 123 public ByteOrder getByteOrder() {
93a45b54 124 return fStreamInput.getStream().getTrace().getByteOrder();
866e5b51
FC
125 }
126
9ac2eb62
MK
127 /**
128 * Gets the name of the stream (it's an id and a number)
129 *
130 * @return gets the stream name (it's a number)
131 */
866e5b51 132 public int getName() {
93a45b54 133 return fId;
866e5b51
FC
134 }
135
9ac2eb62
MK
136 /**
137 * Sets the name of the stream
138 *
139 * @param name
140 * the name of the stream, (it's a number)
141 */
866e5b51 142 public void setName(int name) {
93a45b54 143 fId = name;
866e5b51
FC
144 }
145
9ac2eb62
MK
146 /**
147 * Gets the CPU of a stream. It's the same as the one in /proc or running
148 * the asm CPUID instruction
149 *
150 * @return The CPU id (a number)
151 */
866e5b51 152 public int getCPU() {
93a45b54 153 return fPacketReader.getCPU();
866e5b51
FC
154 }
155
9ac2eb62
MK
156 /**
157 * Gets the filename of the stream being read
db8e8f7d 158 *
9ac2eb62
MK
159 * @return The filename of the stream being read
160 */
ce2388e0 161 public String getFilename() {
93a45b54 162 return fStreamInput.getFilename();
ce2388e0
FC
163 }
164
165 /*
166 * for internal use only
167 */
d84419e1 168 CTFStreamInput getStreamInput() {
93a45b54 169 return fStreamInput;
ce2388e0
FC
170 }
171
53359017
MK
172 /**
173 * Gets the event definition set for this StreamInput
174 *
175 * @return Unmodifiable set with the event definitions
53359017
MK
176 */
177 public Iterable<IEventDeclaration> getEventDeclarations() {
5f715709 178 return ImmutableList.copyOf(fStreamInput.getStream().getEventDeclarations());
53359017
MK
179 }
180
6a5251eb
MK
181 /**
182 * Set the trace to live mode
183 *
184 * @param live
185 * whether the trace is read live or not
6a5251eb
MK
186 */
187 public void setLive(boolean live) {
188 fLive = live;
189 }
190
191 /**
192 * Get if the trace is to read live or not
193 *
194 * @return whether the trace is live or not
6a5251eb
MK
195 */
196 public boolean isLive() {
197 return fLive;
198 }
199
a4fa4e36
MK
200 /**
201 * Get the event context of the stream
202 *
203 * @return the event context declaration of the stream
a4fa4e36
MK
204 */
205 public StructDeclaration getStreamEventContextDecl() {
206 return getStreamInput().getStream().getEventContextDecl();
207 }
208
866e5b51
FC
209 // ------------------------------------------------------------------------
210 // Operations
211 // ------------------------------------------------------------------------
212 /**
213 * Reads the next event in the current event variable.
214 *
215 * @return If an event has been successfully read.
db8e8f7d
AM
216 * @throws CTFReaderException
217 * if an error occurs
866e5b51 218 */
6a5251eb 219 public CTFResponse readNextEvent() throws CTFReaderException {
bfe038ff 220
866e5b51
FC
221 /*
222 * Change packet if needed
223 */
93a45b54
MK
224 if (!fPacketReader.hasMoreEvents()) {
225 final StreamInputPacketIndexEntry prevPacket = fPacketReader
bfe038ff 226 .getCurrentPacket();
a4fa4e36 227 if (prevPacket != null || fLive) {
bfe038ff 228 goToNextPacket();
bfe038ff 229 }
6a5251eb 230
866e5b51
FC
231 }
232
32ede2ec 233 /*
866e5b51
FC
234 * If an event is available, read it.
235 */
93a45b54 236 if (fPacketReader.hasMoreEvents()) {
6a5251eb
MK
237 setCurrentEvent(fPacketReader.readNextEvent());
238 return CTFResponse.OK;
866e5b51
FC
239 }
240 this.setCurrentEvent(null);
6a5251eb 241 return fLive ? CTFResponse.WAIT : CTFResponse.FINISH;
866e5b51
FC
242 }
243
244 /**
245 * Change the current packet of the packet reader to the next one.
db8e8f7d
AM
246 *
247 * @throws CTFReaderException
248 * if an error occurs
866e5b51 249 */
db8e8f7d 250 private void goToNextPacket() throws CTFReaderException {
93a45b54 251 fPacketIndex++;
6a5251eb 252 // did we already index the packet?
93a45b54
MK
253 if (getPacketSize() >= (fPacketIndex + 1)) {
254 fPacketReader.setCurrentPacket(getPacket());
866e5b51 255 } else {
6a5251eb 256 // go to the next packet if there is one, index it at the same time
93a45b54
MK
257 if (fStreamInput.addPacketHeaderIndex()) {
258 fPacketIndex = getPacketSize() - 1;
259 fPacketReader.setCurrentPacket(getPacket());
cf9a28da 260 } else {
6a5251eb 261 // out of packets
93a45b54 262 fPacketReader.setCurrentPacket(null);
bfe038ff 263 }
866e5b51
FC
264 }
265 }
266
bfe038ff
MK
267 /**
268 * @return
269 */
270 private int getPacketSize() {
93a45b54 271 return fStreamInput.getIndex().getEntries().size();
bfe038ff
MK
272 }
273
866e5b51
FC
274 /**
275 * Changes the location of the trace file reader so that the current event
ecb12461 276 * is the first event with a timestamp greater or equal the given timestamp.
866e5b51
FC
277 *
278 * @param timestamp
279 * The timestamp to seek to.
be6df2d8 280 * @return The offset compared to the current position
db8e8f7d
AM
281 * @throws CTFReaderException
282 * if an error occurs
866e5b51 283 */
db8e8f7d 284 public long seek(long timestamp) throws CTFReaderException {
ce2388e0 285 long offset = 0;
866e5b51 286
eb94f9c9 287 gotoPacket(timestamp);
866e5b51 288
0c59c1a6
MK
289 /*
290 * index up to the desired timestamp.
291 */
93a45b54
MK
292 while ((fPacketReader.getCurrentPacket() != null)
293 && (fPacketReader.getCurrentPacket().getTimestampEnd() < timestamp)) {
0c59c1a6 294 try {
93a45b54 295 fStreamInput.addPacketHeaderIndex();
0c59c1a6
MK
296 goToNextPacket();
297 } catch (CTFReaderException e) {
298 // do nothing here
299 }
300 }
93a45b54 301 if (fPacketReader.getCurrentPacket() == null) {
eb94f9c9
MK
302 gotoPacket(timestamp);
303 }
0c59c1a6 304
866e5b51 305 /*
6a5251eb
MK
306 * Advance until either of these conditions are met:
307 *
308 * - reached the end of the trace file (the given timestamp is after the
309 * last event)
310 *
311 * - found the first event with a timestamp greater or equal the given
312 * timestamp.
866e5b51
FC
313 */
314 readNextEvent();
315 boolean done = (this.getCurrentEvent() == null);
aa572e22 316 while (!done && (this.getCurrentEvent().getTimestamp() < timestamp)) {
866e5b51
FC
317 readNextEvent();
318 done = (this.getCurrentEvent() == null);
ce2388e0 319 offset++;
866e5b51 320 }
ce2388e0
FC
321 return offset;
322 }
323
eb94f9c9
MK
324 /**
325 * @param timestamp
6a5251eb 326 * the time to seek
db8e8f7d
AM
327 * @throws CTFReaderException
328 * if an error occurs
eb94f9c9 329 */
db8e8f7d 330 private void gotoPacket(long timestamp) throws CTFReaderException {
93a45b54 331 fPacketIndex = fStreamInput.getIndex().search(timestamp)
eb94f9c9
MK
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 */
93a45b54 349 final int len = fStreamInput.getIndex().getEntries().size();
ec6f5beb 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 */
93a45b54 358 if ((len == 0) || (fPacketReader.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 367 for (int pos = len - 1; pos > 0; pos--) {
93a45b54
MK
368 fPacketIndex = pos;
369 fPacketReader.setCurrentPacket(getPacket());
370 if (fPacketReader.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;
93a45b54
MK
379 while (fCurrentEvent != null) {
380 prevEvent = fCurrentEvent;
ec6f5beb
MK
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() {
93a45b54 393 return fParent;
bfe038ff
MK
394 }
395
396 /**
397 * @param parent
398 * the parent to set
399 */
400 public void setParent(CTFTraceReader parent) {
93a45b54 401 fParent = parent;
bfe038ff
MK
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 410 public void setCurrentEvent(EventDefinition currentEvent) {
93a45b54 411 fCurrentEvent = currentEvent;
866e5b51
FC
412 }
413
ce2388e0
FC
414 /**
415 * @return the packetIndexIt
416 */
bfe038ff 417 private int getPacketIndex() {
93a45b54 418 return fPacketIndex;
bfe038ff
MK
419 }
420
421 private StreamInputPacketIndexEntry getPacket() {
93a45b54 422 return fStreamInput.getIndex().getEntries().get(getPacketIndex());
ce2388e0
FC
423 }
424
425 /**
426 * @return the packetReader
427 */
d84419e1 428 public CTFStreamInputPacketReader getPacketReader() {
93a45b54 429 return fPacketReader;
ce2388e0
FC
430 }
431
81c8e6f7
MK
432 @Override
433 public int hashCode() {
434 final int prime = 31;
435 int result = 1;
93a45b54 436 result = (prime * result) + fId;
81c8e6f7 437 result = (prime * result)
70f60307 438 + fStreamInput.hashCode();
81c8e6f7
MK
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 }
d84419e1 450 if (!(obj instanceof CTFStreamInputReader)) {
81c8e6f7
MK
451 return false;
452 }
d84419e1 453 CTFStreamInputReader other = (CTFStreamInputReader) obj;
93a45b54 454 if (fId != other.fId) {
81c8e6f7
MK
455 return false;
456 }
70f60307 457 return fStreamInput.equals(other.fStreamInput);
81c8e6f7
MK
458 }
459
87b60a47
MK
460 @Override
461 public String toString() {
462 // this helps debugging
93a45b54 463 return fId + ' ' + fCurrentEvent.toString();
87b60a47 464 }
866e5b51 465}
This page took 0.071886 seconds and 5 git commands to generate.