1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
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
10 * Matthew Khouzam - Initial API and implementation
11 * Florian Wininger - Performance improvements
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.iterator
;
16 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFReaderException
;
17 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFStreamInputReader
;
18 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTraceReader
;
19 import org
.eclipse
.tracecompass
.internal
.tmf
.ctf
.core
.Activator
;
20 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
21 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
22 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfLocation
;
23 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfLocationInfo
;
24 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
.CtfTmfEvent
;
25 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
.CtfTmfEventFactory
;
26 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.CtfTmfTrace
;
29 * The CTF trace reader iterator.
31 * It doesn't reserve a file handle, so many iterators can be used without
32 * worries of I/O errors or resource exhaustion.
34 * @author Matthew Khouzam
36 public class CtfIterator
extends CTFTraceReader
37 implements ITmfContext
, Comparable
<CtfIterator
> {
39 /** An invalid location */
40 public static final CtfLocation NULL_LOCATION
= new CtfLocation(CtfLocation
.INVALID_LOCATION
);
42 private final CtfTmfTrace fTrace
;
44 private CtfLocation fCurLocation
;
45 private long fCurRank
;
47 private CtfLocation fPreviousLocation
;
48 private CtfTmfEvent fPreviousEvent
;
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
55 * Create a new CTF trace iterator, which initially points at the first
59 * The trace to iterate over
60 * @throws CTFReaderException
61 * If the iterator couldn't not be instantiated, probably due to
64 public CtfIterator(CtfTmfTrace trace
) throws CTFReaderException
{
65 super(trace
.getCTFTrace());
67 if (hasMoreEvents()) {
68 fCurLocation
= new CtfLocation(trace
.getStartTime());
76 * Create a new CTF trace iterator, which will initially point to the given
80 * The trace to iterate over
81 * @param ctfLocationData
82 * The initial timestamp the iterator will be pointing to
85 * @throws CTFReaderException
86 * If the iterator couldn't not be instantiated, probably due to
90 public CtfIterator(CtfTmfTrace trace
, CtfLocationInfo ctfLocationData
, long rank
)
91 throws CTFReaderException
{
92 super(trace
.getCTFTrace());
95 if (this.hasMoreEvents()) {
96 this.fCurLocation
= new CtfLocation(ctfLocationData
);
97 if (this.getCurrentEvent().getTimestamp().getValue() != ctfLocationData
.getTimestamp()) {
98 this.seek(ctfLocationData
);
102 setUnknownLocation();
107 public void dispose() {
111 private void setUnknownLocation() {
112 fCurLocation
= NULL_LOCATION
;
113 fCurRank
= UNKNOWN_RANK
;
116 // ------------------------------------------------------------------------
118 // ------------------------------------------------------------------------
121 * Return this iterator's trace.
123 * @return CtfTmfTrace The iterator's trace
125 public CtfTmfTrace
getCtfTmfTrace() {
130 * Return the current event pointed to by the iterator.
132 * @return CtfTmfEvent The current event
134 public synchronized CtfTmfEvent
getCurrentEvent() {
135 final CTFStreamInputReader top
= super.getPrio().peek();
137 if (!fCurLocation
.equals(fPreviousLocation
)) {
138 fPreviousLocation
= fCurLocation
;
139 fPreviousEvent
= CtfTmfEventFactory
.createEvent(top
.getCurrentEvent(),
140 top
.getFilename(), fTrace
);
142 return fPreviousEvent
;
148 * Return the current timestamp location pointed to by the iterator.
149 * This is the timestamp for use in CtfLocation, not the event timestamp.
151 * @return long The current timestamp location
153 public synchronized long getCurrentTimestamp() {
154 final CTFStreamInputReader top
= super.getPrio().peek();
156 long ts
= top
.getCurrentEvent().getTimestamp();
157 return fTrace
.getCTFTrace().timestampCyclesToNanos(ts
);
163 * Seek this iterator to a given location.
165 * @param ctfLocationData
166 * The LocationData representing the position to seek to
167 * @return boolean True if the seek was successful, false if there was an
171 public synchronized boolean seek(CtfLocationInfo ctfLocationData
) {
174 /* Avoid the cost of seeking at the current location. */
175 if (fCurLocation
.getLocationInfo().equals(ctfLocationData
)) {
176 return super.hasMoreEvents();
179 /* Adjust the timestamp depending on the trace's offset */
180 long currTimestamp
= ctfLocationData
.getTimestamp();
181 final long offsetTimestamp
= this.getCtfTmfTrace().getCTFTrace().timestampNanoToCycles(currTimestamp
);
183 if (offsetTimestamp
< 0) {
184 ret
= super.seek(0L);
186 ret
= super.seek(offsetTimestamp
);
188 } catch (CTFReaderException e
) {
189 Activator
.getDefault().logError(e
.getMessage(), e
);
193 * Check if there is already one or more events for that timestamp, and
194 * assign the location index correctly
197 final CtfTmfEvent currentEvent
= this.getCurrentEvent();
198 if (currentEvent
!= null) {
199 currTimestamp
= currentEvent
.getTimestamp().getValue();
201 for (long i
= 0; i
< ctfLocationData
.getIndex(); i
++) {
202 if (currTimestamp
== currentEvent
.getTimestamp().getValue()) {
212 /* Seek the current location accordingly */
214 fCurLocation
= new CtfLocation(new CtfLocationInfo(getCurrentEvent().getTimestamp().getValue(), index
));
216 fCurLocation
= NULL_LOCATION
;
222 // ------------------------------------------------------------------------
224 // ------------------------------------------------------------------------
227 public boolean seek(long timestamp
) {
228 return seek(new CtfLocationInfo(timestamp
, 0));
232 public synchronized boolean advance() {
235 ret
= super.advance();
236 } catch (CTFReaderException e
) {
237 Activator
.getDefault().logError(e
.getMessage(), e
);
241 long timestamp
= fCurLocation
.getLocationInfo().getTimestamp();
242 final long timestampValue
= getCurrentTimestamp();
243 if (timestamp
== timestampValue
) {
244 long index
= fCurLocation
.getLocationInfo().getIndex();
245 fCurLocation
= new CtfLocation(timestampValue
, index
+ 1);
247 fCurLocation
= new CtfLocation(timestampValue
, 0L);
250 fCurLocation
= NULL_LOCATION
;
255 // ------------------------------------------------------------------------
257 // ------------------------------------------------------------------------
260 public long getRank() {
265 public void setRank(long rank
) {
270 public void increaseRank() {
271 /* Only increase the rank if it's valid */
272 if (hasValidRank()) {
278 public boolean hasValidRank() {
279 return (getRank() >= 0);
286 public void setLocation(ITmfLocation location
) {
287 // FIXME alex: isn't there a cleaner way than a cast here?
288 fCurLocation
= (CtfLocation
) location
;
289 seek(((CtfLocation
) location
).getLocationInfo());
293 public CtfLocation
getLocation() {
297 // ------------------------------------------------------------------------
299 // ------------------------------------------------------------------------
302 public int compareTo(final CtfIterator o
) {
303 if (getRank() < o
.getRank()) {
305 } else if (getRank() > o
.getRank()) {
311 // ------------------------------------------------------------------------
313 // ------------------------------------------------------------------------
316 public int hashCode() {
317 final int prime
= 31;
318 int result
= super.hashCode();
319 result
= (prime
* result
)
320 + ((fTrace
== null) ?
0 : fTrace
.hashCode());
321 result
= (prime
* result
)
322 + ((fCurLocation
== null) ?
0 : fCurLocation
.hashCode());
323 result
= (prime
* result
) + (int) (fCurRank ^
(fCurRank
>>> 32));
328 public boolean equals(Object obj
) {
332 if (!super.equals(obj
)) {
335 if (!(obj
instanceof CtfIterator
)) {
338 CtfIterator other
= (CtfIterator
) obj
;
339 if (fTrace
== null) {
340 if (other
.fTrace
!= null) {
343 } else if (!fTrace
.equals(other
.fTrace
)) {
346 if (fCurLocation
== null) {
347 if (other
.fCurLocation
!= null) {
350 } else if (!fCurLocation
.equals(other
.fCurLocation
)) {
353 if (fCurRank
!= other
.fCurRank
) {