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