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
.internal
.tmf
.ctf
.core
.trace
.iterator
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.equalsNullable
;
19 import org
.eclipse
.jdt
.annotation
.NonNull
;
20 import org
.eclipse
.tracecompass
.ctf
.core
.CTFException
;
21 import org
.eclipse
.tracecompass
.ctf
.core
.event
.EventDefinition
;
22 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFStreamInputReader
;
23 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTrace
;
24 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTraceReader
;
25 import org
.eclipse
.tracecompass
.internal
.tmf
.ctf
.core
.Activator
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
28 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfLocation
;
29 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfLocationInfo
;
30 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
.CtfTmfEvent
;
31 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.CtfTmfTrace
;
34 * The CTF trace reader iterator.
36 * It doesn't reserve a file handle, so many iterators can be used without
37 * worries of I/O errors or resource exhaustion.
39 * @author Matthew Khouzam
41 public class CtfIterator
extends CTFTraceReader
42 implements ITmfContext
, Comparable
<CtfIterator
> {
44 /** An invalid location */
45 public static final CtfLocation NULL_LOCATION
= new CtfLocation(CtfLocation
.INVALID_LOCATION
);
47 private final @NonNull CtfTmfTrace fTrace
;
49 private CtfLocation fCurLocation
;
50 private long fCurRank
;
52 private CtfLocation fPreviousLocation
;
53 private CtfTmfEvent fPreviousEvent
;
55 // ------------------------------------------------------------------------
57 // ------------------------------------------------------------------------
60 * Create a new CTF trace iterator, which initially points at the first
64 * The {@link CTFTrace} linked to the trace. It should be
65 * provided by the corresponding 'ctfTmfTrace'.
68 * The {@link CtfTmfTrace} to iterate over
69 * @throws CTFException
70 * If the iterator couldn't not be instantiated, probably due to
73 public CtfIterator(CTFTrace ctfTrace
, @NonNull CtfTmfTrace ctfTmfTrace
) throws CTFException
{
76 if (hasMoreEvents()) {
77 fCurLocation
= new CtfLocation(ctfTmfTrace
.getStartTime());
85 * Create a new CTF trace iterator, which will initially point to the given
89 * The {@link CTFTrace} linked to the trace. It should be
90 * provided by the corresponding 'ctfTmfTrace'.
92 * The {@link CtfTmfTrace} to iterate over
93 * @param ctfLocationData
94 * The initial timestamp the iterator will be pointing to
97 * @throws CTFException
98 * If the iterator couldn't not be instantiated, probably due to
101 public CtfIterator(CTFTrace ctfTrace
, @NonNull CtfTmfTrace ctfTmfTrace
, CtfLocationInfo ctfLocationData
, long rank
)
102 throws CTFException
{
105 this.fTrace
= ctfTmfTrace
;
106 if (this.hasMoreEvents()) {
107 this.fCurLocation
= new CtfLocation(ctfLocationData
);
108 if (this.getCurrentEvent().getTimestamp().getValue() != ctfLocationData
.getTimestamp()) {
109 this.seek(ctfLocationData
);
110 this.fCurRank
= rank
;
113 setUnknownLocation();
118 public void dispose() {
122 private void setUnknownLocation() {
123 fCurLocation
= NULL_LOCATION
;
124 fCurRank
= UNKNOWN_RANK
;
127 // ------------------------------------------------------------------------
129 // ------------------------------------------------------------------------
132 * Return this iterator's trace.
134 * @return CtfTmfTrace The iterator's trace
136 public CtfTmfTrace
getCtfTmfTrace() {
141 * Return the current event pointed to by the iterator.
143 * @return CtfTmfEvent The current event
145 public synchronized CtfTmfEvent
getCurrentEvent() {
146 final CTFStreamInputReader top
= super.getPrio().peek();
148 if (!fCurLocation
.equals(fPreviousLocation
)) {
149 fPreviousLocation
= fCurLocation
;
150 fPreviousEvent
= fTrace
.getEventFactory().createEvent(fTrace
, checkNotNull(top
.getCurrentEvent()), top
.getFilename());
152 return fPreviousEvent
;
158 * Return the current timestamp location pointed to by the iterator. This is
159 * the timestamp for use in CtfLocation, not the event timestamp.
161 * @return long The current timestamp location
163 public synchronized long getCurrentTimestamp() {
164 final CTFStreamInputReader top
= super.getPrio().peek();
166 EventDefinition currentEvent
= top
.getCurrentEvent();
167 if (currentEvent
!= null) {
168 long ts
= currentEvent
.getTimestamp();
169 return fTrace
.timestampCyclesToNanos(ts
);
176 * Seek this iterator to a given location.
178 * @param ctfLocationData
179 * The LocationData representing the position to seek to
180 * @return boolean True if the seek was successful, false if there was an
183 public synchronized boolean seek(CtfLocationInfo ctfLocationData
) {
185 if (ctfLocationData
.equals(CtfLocation
.INVALID_LOCATION
)) {
186 fCurLocation
= NULL_LOCATION
;
190 /* Avoid the cost of seeking at the current location. */
191 if (fCurLocation
.getLocationInfo().equals(ctfLocationData
)) {
192 return super.hasMoreEvents();
194 /* Update location to make sure the current event is updated */
195 fCurLocation
= new CtfLocation(ctfLocationData
);
197 /* Adjust the timestamp depending on the trace's offset */
198 long currTimestamp
= ctfLocationData
.getTimestamp();
199 final long offsetTimestamp
= this.getCtfTmfTrace().timestampNanoToCycles(currTimestamp
);
201 if (offsetTimestamp
< 0) {
202 ret
= super.seek(0L);
204 ret
= super.seek(offsetTimestamp
);
206 } catch (CTFException e
) {
207 Activator
.getDefault().logError(e
.getMessage(), e
);
211 * Check if there is already one or more events for that timestamp, and
212 * assign the location index correctly
215 final CtfTmfEvent currentEvent
= this.getCurrentEvent();
216 if (currentEvent
!= null) {
217 currTimestamp
= currentEvent
.getTimestamp().getValue();
219 for (long i
= 0; i
< ctfLocationData
.getIndex(); i
++) {
220 if (currTimestamp
== currentEvent
.getTimestamp().getValue()) {
230 /* Seek the current location accordingly */
232 fCurLocation
= new CtfLocation(new CtfLocationInfo(getCurrentEvent().getTimestamp().getValue(), index
));
234 fCurLocation
= NULL_LOCATION
;
240 // ------------------------------------------------------------------------
242 // ------------------------------------------------------------------------
245 public boolean seek(long timestamp
) {
246 return seek(new CtfLocationInfo(timestamp
, 0));
250 public synchronized boolean advance() {
253 ret
= super.advance();
254 } catch (CTFException e
) {
255 Activator
.getDefault().logError(e
.getMessage(), e
);
259 long timestamp
= fCurLocation
.getLocationInfo().getTimestamp();
260 final long timestampValue
= getCurrentTimestamp();
261 if (timestamp
== timestampValue
) {
262 long index
= fCurLocation
.getLocationInfo().getIndex();
263 fCurLocation
= new CtfLocation(timestampValue
, index
+ 1);
265 fCurLocation
= new CtfLocation(timestampValue
, 0L);
268 fCurLocation
= NULL_LOCATION
;
273 // ------------------------------------------------------------------------
275 // ------------------------------------------------------------------------
278 public long getRank() {
283 public void setRank(long rank
) {
288 public void increaseRank() {
289 /* Only increase the rank if it's valid */
290 if (hasValidRank()) {
296 public boolean hasValidRank() {
297 return (getRank() >= 0);
301 public void setLocation(ITmfLocation location
) {
302 // FIXME alex: isn't there a cleaner way than a cast here?
303 fCurLocation
= (CtfLocation
) location
;
304 seek(((CtfLocation
) location
).getLocationInfo());
308 public CtfLocation
getLocation() {
312 // ------------------------------------------------------------------------
314 // ------------------------------------------------------------------------
317 public int compareTo(final CtfIterator o
) {
318 if (getRank() < o
.getRank()) {
320 } else if (getRank() > o
.getRank()) {
326 // ------------------------------------------------------------------------
328 // ------------------------------------------------------------------------
331 public int hashCode() {
332 final int prime
= 31;
333 int result
= super.hashCode();
334 result
= (prime
* result
) + fTrace
.hashCode();
335 result
= (prime
* result
)
336 + ((fCurLocation
== null) ?
0 : fCurLocation
.hashCode());
337 result
= (prime
* result
) + (int) (fCurRank ^
(fCurRank
>>> 32));
342 public boolean equals(Object obj
) {
346 if (!super.equals(obj
)) {
349 if (!(obj
instanceof CtfIterator
)) {
352 CtfIterator other
= (CtfIterator
) obj
;
353 if (!equalsNullable(fTrace
, other
.fTrace
)) {
356 if (!equalsNullable(fCurLocation
, other
.fCurLocation
)) {
359 if (fCurRank
!= other
.fCurRank
) {