ctf: Fix unreliable handling of invalid location
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.tmf.ctf.core / src / org / eclipse / tracecompass / internal / tmf / ctf / core / trace / iterator / CtfIterator.java
CommitLineData
b1baa808 1/*******************************************************************************
fab7b404 2 * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
b1baa808
MK
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 *
5b020488
AM
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
fab7b404 11 * Florian Wininger - Performance improvements
b1baa808 12 *******************************************************************************/
5b020488 13
fe71057b 14package org.eclipse.tracecompass.internal.tmf.ctf.core.trace.iterator;
a3fc8213 15
c052c341
MK
16import static org.eclipse.tracecompass.common.core.NonNullUtils.equalsNullable;
17
680f9173 18import org.eclipse.tracecompass.ctf.core.CTFException;
f357bcd4 19import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
fe71057b 20import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
f357bcd4 21import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader;
2bdf0193
AM
22import org.eclipse.tracecompass.internal.tmf.ctf.core.Activator;
23import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
24import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
9722e5d7
AM
25import org.eclipse.tracecompass.tmf.ctf.core.context.CtfLocation;
26import org.eclipse.tracecompass.tmf.ctf.core.context.CtfLocationInfo;
27import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent;
28import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEventFactory;
29import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace;
a3fc8213 30
b1baa808 31/**
d09f973b 32 * The CTF trace reader iterator.
3eaea7e6 33 *
db8e8f7d
AM
34 * It doesn't reserve a file handle, so many iterators can be used without
35 * worries of I/O errors or resource exhaustion.
3eaea7e6 36 *
d09f973b 37 * @author Matthew Khouzam
b1baa808 38 */
5b020488
AM
39public class CtfIterator extends CTFTraceReader
40 implements ITmfContext, Comparable<CtfIterator> {
a3fc8213 41
5b020488 42 /** An invalid location */
db8e8f7d 43 public static final CtfLocation NULL_LOCATION = new CtfLocation(CtfLocation.INVALID_LOCATION);
132a02b0 44
5b020488
AM
45 private final CtfTmfTrace fTrace;
46
47 private CtfLocation fCurLocation;
48 private long fCurRank;
49
fab7b404
FW
50 private CtfLocation fPreviousLocation;
51 private CtfTmfEvent fPreviousEvent;
52
5b020488
AM
53 // ------------------------------------------------------------------------
54 // Constructors
55 // ------------------------------------------------------------------------
a3fc8213
AM
56
57 /**
58 * Create a new CTF trace iterator, which initially points at the first
59 * event in the trace.
60 *
fe71057b
AM
61 * @param ctfTrace
62 * The {@link CTFTrace} linked to the trace. It should be
63 * provided by the corresponding 'ctfTmfTrace'.
64 *
65 * @param ctfTmfTrace
66 * The {@link CtfTmfTrace} to iterate over
680f9173 67 * @throws CTFException
5b020488
AM
68 * If the iterator couldn't not be instantiated, probably due to
69 * a read error.
a3fc8213 70 */
680f9173 71 public CtfIterator(CTFTrace ctfTrace, CtfTmfTrace ctfTmfTrace) throws CTFException {
fe71057b
AM
72 super(ctfTrace);
73 fTrace = ctfTmfTrace;
9d819ac7 74 if (hasMoreEvents()) {
fe71057b 75 fCurLocation = new CtfLocation(ctfTmfTrace.getStartTime());
5b020488 76 fCurRank = 0;
57c073c5
MK
77 } else {
78 setUnknownLocation();
79 }
a3fc8213
AM
80 }
81
b1baa808 82 /**
5b020488
AM
83 * Create a new CTF trace iterator, which will initially point to the given
84 * location/rank.
132a02b0 85 *
fe71057b
AM
86 * @param ctfTrace
87 * The {@link CTFTrace} linked to the trace. It should be
88 * provided by the corresponding 'ctfTmfTrace'.
89 * @param ctfTmfTrace
90 * The {@link CtfTmfTrace} to iterate over
132a02b0 91 * @param ctfLocationData
5b020488 92 * The initial timestamp the iterator will be pointing to
132a02b0 93 * @param rank
5b020488 94 * The initial rank
680f9173 95 * @throws CTFException
5b020488
AM
96 * If the iterator couldn't not be instantiated, probably due to
97 * a read error.
b1baa808 98 */
fe71057b 99 public CtfIterator(CTFTrace ctfTrace, CtfTmfTrace ctfTmfTrace, CtfLocationInfo ctfLocationData, long rank)
680f9173 100 throws CTFException {
fe71057b 101 super(ctfTrace);
57c073c5 102
fe71057b 103 this.fTrace = ctfTmfTrace;
57c073c5 104 if (this.hasMoreEvents()) {
5b020488 105 this.fCurLocation = new CtfLocation(ctfLocationData);
58f3bc52 106 if (this.getCurrentEvent().getTimestamp().getValue() != ctfLocationData.getTimestamp()) {
132a02b0 107 this.seek(ctfLocationData);
5b020488 108 this.fCurRank = rank;
57c073c5
MK
109 }
110 } else {
111 setUnknownLocation();
112 }
a3fc8213
AM
113 }
114
dd9752d5
AM
115 @Override
116 public void dispose() {
117 close();
118 }
119
5b020488
AM
120 private void setUnknownLocation() {
121 fCurLocation = NULL_LOCATION;
122 fCurRank = UNKNOWN_RANK;
123 }
124
125 // ------------------------------------------------------------------------
126 // Accessors
127 // ------------------------------------------------------------------------
128
b1baa808 129 /**
5b020488 130 * Return this iterator's trace.
db8e8f7d 131 *
5b020488 132 * @return CtfTmfTrace The iterator's trace
b1baa808 133 */
a3fc8213 134 public CtfTmfTrace getCtfTmfTrace() {
5b020488 135 return fTrace;
a3fc8213
AM
136 }
137
b1baa808 138 /**
5b020488 139 * Return the current event pointed to by the iterator.
db8e8f7d 140 *
5b020488 141 * @return CtfTmfEvent The current event
b1baa808 142 */
fab7b404 143 public synchronized CtfTmfEvent getCurrentEvent() {
d84419e1 144 final CTFStreamInputReader top = super.getPrio().peek();
57c073c5 145 if (top != null) {
fab7b404
FW
146 if (!fCurLocation.equals(fPreviousLocation)) {
147 fPreviousLocation = fCurLocation;
148 fPreviousEvent = CtfTmfEventFactory.createEvent(top.getCurrentEvent(),
149 top.getFilename(), fTrace);
150 }
151 return fPreviousEvent;
57c073c5 152 }
a3fc8213
AM
153 return null;
154 }
155
962fb72f 156 /**
c052c341
MK
157 * Return the current timestamp location pointed to by the iterator. This is
158 * the timestamp for use in CtfLocation, not the event timestamp.
962fb72f
PT
159 *
160 * @return long The current timestamp location
161 */
162 public synchronized long getCurrentTimestamp() {
163 final CTFStreamInputReader top = super.getPrio().peek();
164 if (top != null) {
165 long ts = top.getCurrentEvent().getTimestamp();
fe71057b 166 return fTrace.timestampCyclesToNanos(ts);
962fb72f
PT
167 }
168 return 0;
169 }
170
b1baa808 171 /**
132a02b0
MK
172 * Seek this iterator to a given location.
173 *
174 * @param ctfLocationData
175 * The LocationData representing the position to seek to
db8e8f7d
AM
176 * @return boolean True if the seek was successful, false if there was an
177 * error seeking.
b1baa808 178 */
5b020488 179 public synchronized boolean seek(CtfLocationInfo ctfLocationData) {
a3fc8213 180 boolean ret = false;
21924e03
MAL
181 if (ctfLocationData.equals(CtfLocation.INVALID_LOCATION)) {
182 fCurLocation = NULL_LOCATION;
183 return false;
184 }
132a02b0 185
92d542eb 186 /* Avoid the cost of seeking at the current location. */
5b020488 187 if (fCurLocation.getLocationInfo().equals(ctfLocationData)) {
92d542eb
EB
188 return super.hasMoreEvents();
189 }
5b17357d
PT
190 /* Update location to make sure the current event is updated */
191 fCurLocation = new CtfLocation(ctfLocationData);
92d542eb 192
132a02b0
MK
193 /* Adjust the timestamp depending on the trace's offset */
194 long currTimestamp = ctfLocationData.getTimestamp();
fe71057b 195 final long offsetTimestamp = this.getCtfTmfTrace().timestampNanoToCycles(currTimestamp);
db8e8f7d
AM
196 try {
197 if (offsetTimestamp < 0) {
198 ret = super.seek(0L);
199 } else {
200 ret = super.seek(offsetTimestamp);
201 }
680f9173 202 } catch (CTFException e) {
91e7f946 203 Activator.getDefault().logError(e.getMessage(), e);
db8e8f7d 204 return false;
57c073c5 205 }
132a02b0
MK
206 /*
207 * Check if there is already one or more events for that timestamp, and
208 * assign the location index correctly
209 */
132a02b0 210 long index = 0;
b6220b93
MK
211 final CtfTmfEvent currentEvent = this.getCurrentEvent();
212 if (currentEvent != null) {
213 currTimestamp = currentEvent.getTimestamp().getValue();
77ef700d
MK
214
215 for (long i = 0; i < ctfLocationData.getIndex(); i++) {
b6220b93 216 if (currTimestamp == currentEvent.getTimestamp().getValue()) {
77ef700d
MK
217 index++;
218 } else {
219 index = 0;
220 }
221 this.advance();
132a02b0 222 }
77ef700d 223 } else {
ecb12461 224 ret = false;
132a02b0 225 }
132a02b0 226 /* Seek the current location accordingly */
57c073c5 227 if (ret) {
5b020488 228 fCurLocation = new CtfLocation(new CtfLocationInfo(getCurrentEvent().getTimestamp().getValue(), index));
f474d36b 229 } else {
5b020488 230 fCurLocation = NULL_LOCATION;
57c073c5 231 }
ecb12461 232
ce2388e0
FC
233 return ret;
234 }
235
5b020488
AM
236 // ------------------------------------------------------------------------
237 // CTFTraceReader
238 // ------------------------------------------------------------------------
a3fc8213
AM
239
240 @Override
5b020488
AM
241 public boolean seek(long timestamp) {
242 return seek(new CtfLocationInfo(timestamp, 0));
a3fc8213
AM
243 }
244
a3fc8213 245 @Override
5b020488 246 public synchronized boolean advance() {
5b020488 247 boolean ret = false;
db8e8f7d 248 try {
5b020488 249 ret = super.advance();
680f9173 250 } catch (CTFException e) {
91e7f946 251 Activator.getDefault().logError(e.getMessage(), e);
db8e8f7d 252 }
a3fc8213 253
5b020488 254 if (ret) {
962fb72f
PT
255 long timestamp = fCurLocation.getLocationInfo().getTimestamp();
256 final long timestampValue = getCurrentTimestamp();
5b020488 257 if (timestamp == timestampValue) {
962fb72f 258 long index = fCurLocation.getLocationInfo().getIndex();
5b020488
AM
259 fCurLocation = new CtfLocation(timestampValue, index + 1);
260 } else {
261 fCurLocation = new CtfLocation(timestampValue, 0L);
262 }
263 } else {
264 fCurLocation = NULL_LOCATION;
265 }
266 return ret;
a3fc8213
AM
267 }
268
5b020488
AM
269 // ------------------------------------------------------------------------
270 // ITmfContext
271 // ------------------------------------------------------------------------
272
a3fc8213 273 @Override
5b020488
AM
274 public long getRank() {
275 return fCurRank;
a3fc8213
AM
276 }
277
278 @Override
5b020488
AM
279 public void setRank(long rank) {
280 fCurRank = rank;
a3fc8213
AM
281 }
282
283 @Override
cbdacf03 284 public void increaseRank() {
4a110860 285 /* Only increase the rank if it's valid */
ecb12461 286 if (hasValidRank()) {
5b020488 287 fCurRank++;
4a110860 288 }
a3fc8213
AM
289 }
290
291 @Override
cbdacf03 292 public boolean hasValidRank() {
bcbea6a6 293 return (getRank() >= 0);
a3fc8213
AM
294 }
295
296 @Override
5b020488
AM
297 public void setLocation(ITmfLocation location) {
298 // FIXME alex: isn't there a cleaner way than a cast here?
299 fCurLocation = (CtfLocation) location;
300 seek(((CtfLocation) location).getLocationInfo());
301 }
132a02b0 302
5b020488
AM
303 @Override
304 public CtfLocation getLocation() {
305 return fCurLocation;
a3fc8213
AM
306 }
307
5b020488
AM
308 // ------------------------------------------------------------------------
309 // Comparable
310 // ------------------------------------------------------------------------
311
a3fc8213 312 @Override
ce2388e0 313 public int compareTo(final CtfIterator o) {
9d819ac7 314 if (getRank() < o.getRank()) {
a3fc8213 315 return -1;
9d819ac7 316 } else if (getRank() > o.getRank()) {
a3fc8213 317 return 1;
57c073c5 318 }
a3fc8213
AM
319 return 0;
320 }
788ddcbc 321
5b020488
AM
322 // ------------------------------------------------------------------------
323 // Object
324 // ------------------------------------------------------------------------
325
b1baa808
MK
326 @Override
327 public int hashCode() {
328 final int prime = 31;
329 int result = super.hashCode();
330 result = (prime * result)
5b020488 331 + ((fTrace == null) ? 0 : fTrace.hashCode());
b1baa808 332 result = (prime * result)
5b020488
AM
333 + ((fCurLocation == null) ? 0 : fCurLocation.hashCode());
334 result = (prime * result) + (int) (fCurRank ^ (fCurRank >>> 32));
b1baa808
MK
335 return result;
336 }
a3fc8213 337
b1baa808
MK
338 @Override
339 public boolean equals(Object obj) {
340 if (this == obj) {
341 return true;
342 }
343 if (!super.equals(obj)) {
344 return false;
345 }
346 if (!(obj instanceof CtfIterator)) {
347 return false;
348 }
349 CtfIterator other = (CtfIterator) obj;
c052c341 350 if (!equalsNullable(fTrace, other.fTrace)) {
b1baa808
MK
351 return false;
352 }
c052c341 353 if (!equalsNullable(fCurLocation, other.fCurLocation)) {
b1baa808
MK
354 return false;
355 }
5b020488 356 if (fCurRank != other.fCurRank) {
b1baa808
MK
357 return false;
358 }
359 return true;
360 }
ce2388e0 361}
This page took 0.09717 seconds and 5 git commands to generate.