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
.linuxtools
.tmf
.ctf
.core
;
16 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFReaderException
;
17 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTraceReader
;
18 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFStreamInputReader
;
19 import org
.eclipse
.linuxtools
.internal
.tmf
.ctf
.core
.Activator
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.location
.ITmfLocation
;
24 * The CTF trace reader iterator.
26 * It doesn't reserve a file handle, so many iterators can be used without
27 * worries of I/O errors or resource exhaustion.
29 * @author Matthew Khouzam
31 public class CtfIterator
extends CTFTraceReader
32 implements ITmfContext
, Comparable
<CtfIterator
> {
34 /** An invalid location */
35 public static final CtfLocation NULL_LOCATION
= new CtfLocation(CtfLocation
.INVALID_LOCATION
);
37 private final CtfTmfTrace fTrace
;
39 private CtfLocation fCurLocation
;
40 private long fCurRank
;
42 private CtfLocation fPreviousLocation
;
43 private CtfTmfEvent fPreviousEvent
;
45 // ------------------------------------------------------------------------
47 // ------------------------------------------------------------------------
50 * Create a new CTF trace iterator, which initially points at the first
54 * The trace to iterate over
55 * @throws CTFReaderException
56 * If the iterator couldn't not be instantiated, probably due to
59 public CtfIterator(CtfTmfTrace trace
) throws CTFReaderException
{
60 super(trace
.getCTFTrace());
62 if (hasMoreEvents()) {
63 fCurLocation
= new CtfLocation(trace
.getStartTime());
71 * Create a new CTF trace iterator, which will initially point to the given
75 * The trace to iterate over
76 * @param ctfLocationData
77 * The initial timestamp the iterator will be pointing to
80 * @throws CTFReaderException
81 * If the iterator couldn't not be instantiated, probably due to
85 public CtfIterator(CtfTmfTrace trace
, CtfLocationInfo ctfLocationData
, long rank
)
86 throws CTFReaderException
{
87 super(trace
.getCTFTrace());
90 if (this.hasMoreEvents()) {
91 this.fCurLocation
= new CtfLocation(ctfLocationData
);
92 if (this.getCurrentEvent().getTimestamp().getValue() != ctfLocationData
.getTimestamp()) {
93 this.seek(ctfLocationData
);
102 public void dispose() {
106 private void setUnknownLocation() {
107 fCurLocation
= NULL_LOCATION
;
108 fCurRank
= UNKNOWN_RANK
;
111 // ------------------------------------------------------------------------
113 // ------------------------------------------------------------------------
116 * Return this iterator's trace.
118 * @return CtfTmfTrace The iterator's trace
120 public CtfTmfTrace
getCtfTmfTrace() {
125 * Return the current event pointed to by the iterator.
127 * @return CtfTmfEvent The current event
129 public synchronized CtfTmfEvent
getCurrentEvent() {
130 final CTFStreamInputReader top
= super.getPrio().peek();
132 if (!fCurLocation
.equals(fPreviousLocation
)) {
133 fPreviousLocation
= fCurLocation
;
134 fPreviousEvent
= CtfTmfEventFactory
.createEvent(top
.getCurrentEvent(),
135 top
.getFilename(), fTrace
);
137 return fPreviousEvent
;
143 * Seek this iterator to a given location.
145 * @param ctfLocationData
146 * The LocationData representing the position to seek to
147 * @return boolean True if the seek was successful, false if there was an
151 public synchronized boolean seek(CtfLocationInfo ctfLocationData
) {
154 /* Avoid the cost of seeking at the current location. */
155 if (fCurLocation
.getLocationInfo().equals(ctfLocationData
)) {
156 return super.hasMoreEvents();
159 /* Adjust the timestamp depending on the trace's offset */
160 long currTimestamp
= ctfLocationData
.getTimestamp();
161 final long offsetTimestamp
= this.getCtfTmfTrace().getCTFTrace().timestampNanoToCycles(currTimestamp
);
163 if (offsetTimestamp
< 0) {
164 ret
= super.seek(0L);
166 ret
= super.seek(offsetTimestamp
);
168 } catch (CTFReaderException e
) {
169 Activator
.getDefault().logError(e
.getMessage(), e
);
173 * Check if there is already one or more events for that timestamp, and
174 * assign the location index correctly
177 final CtfTmfEvent currentEvent
= this.getCurrentEvent();
178 if (currentEvent
!= null) {
179 currTimestamp
= currentEvent
.getTimestamp().getValue();
181 for (long i
= 0; i
< ctfLocationData
.getIndex(); i
++) {
182 if (currTimestamp
== currentEvent
.getTimestamp().getValue()) {
192 /* Seek the current location accordingly */
194 fCurLocation
= new CtfLocation(new CtfLocationInfo(getCurrentEvent().getTimestamp().getValue(), index
));
196 fCurLocation
= NULL_LOCATION
;
202 // ------------------------------------------------------------------------
204 // ------------------------------------------------------------------------
207 public boolean seek(long timestamp
) {
208 return seek(new CtfLocationInfo(timestamp
, 0));
212 public synchronized boolean advance() {
213 long index
= fCurLocation
.getLocationInfo().getIndex();
214 long timestamp
= fCurLocation
.getLocationInfo().getTimestamp();
217 ret
= super.advance();
218 } catch (CTFReaderException e
) {
219 Activator
.getDefault().logError(e
.getMessage(), e
);
223 final long timestampValue
= getCurrentEvent().getTimestamp().getValue();
224 if (timestamp
== timestampValue
) {
225 fCurLocation
= new CtfLocation(timestampValue
, index
+ 1);
227 fCurLocation
= new CtfLocation(timestampValue
, 0L);
230 fCurLocation
= NULL_LOCATION
;
235 // ------------------------------------------------------------------------
237 // ------------------------------------------------------------------------
240 public long getRank() {
245 public void setRank(long rank
) {
250 public void increaseRank() {
251 /* Only increase the rank if it's valid */
252 if (hasValidRank()) {
258 public boolean hasValidRank() {
259 return (getRank() >= 0);
266 public void setLocation(ITmfLocation location
) {
267 // FIXME alex: isn't there a cleaner way than a cast here?
268 fCurLocation
= (CtfLocation
) location
;
269 seek(((CtfLocation
) location
).getLocationInfo());
273 public CtfLocation
getLocation() {
277 // ------------------------------------------------------------------------
279 // ------------------------------------------------------------------------
282 public int compareTo(final CtfIterator o
) {
283 if (getRank() < o
.getRank()) {
285 } else if (getRank() > o
.getRank()) {
291 // ------------------------------------------------------------------------
293 // ------------------------------------------------------------------------
296 public int hashCode() {
297 final int prime
= 31;
298 int result
= super.hashCode();
299 result
= (prime
* result
)
300 + ((fTrace
== null) ?
0 : fTrace
.hashCode());
301 result
= (prime
* result
)
302 + ((fCurLocation
== null) ?
0 : fCurLocation
.hashCode());
303 result
= (prime
* result
) + (int) (fCurRank ^
(fCurRank
>>> 32));
308 public boolean equals(Object obj
) {
312 if (!super.equals(obj
)) {
315 if (!(obj
instanceof CtfIterator
)) {
318 CtfIterator other
= (CtfIterator
) obj
;
319 if (fTrace
== null) {
320 if (other
.fTrace
!= null) {
323 } else if (!fTrace
.equals(other
.fTrace
)) {
326 if (fCurLocation
== null) {
327 if (other
.fCurLocation
!= null) {
330 } else if (!fCurLocation
.equals(other
.fCurLocation
)) {
333 if (fCurRank
!= other
.fCurRank
) {