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