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