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