Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
165c977c | 2 | * Copyright (c) 2009 Ericsson |
8c8bf09f ASL |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made 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 | * Francois Chouinard - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.tmf.trace; | |
14 | ||
62d1696a FC |
15 | import java.io.FileNotFoundException; |
16 | import java.io.IOException; | |
17 | import java.util.Collections; | |
8c8bf09f ASL |
18 | import java.util.Vector; |
19 | ||
62d1696a FC |
20 | import org.eclipse.core.runtime.IProgressMonitor; |
21 | import org.eclipse.core.runtime.IStatus; | |
22 | import org.eclipse.core.runtime.Status; | |
23 | import org.eclipse.core.runtime.jobs.Job; | |
8c8bf09f ASL |
24 | import org.eclipse.linuxtools.tmf.event.TmfEvent; |
25 | import org.eclipse.linuxtools.tmf.event.TmfTimeRange; | |
26 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; | |
50adc88e | 27 | import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; |
8c8bf09f ASL |
28 | |
29 | /** | |
62d1696a | 30 | * <b><u>TmfEventStream</u></b> |
8c8bf09f | 31 | * <p> |
62d1696a | 32 | * TODO: Implement me. Please. |
8c8bf09f | 33 | */ |
62d1696a FC |
34 | public abstract class TmfTrace implements ITmfTrace { |
35 | ||
36 | // ======================================================================== | |
37 | // Constants | |
38 | // ======================================================================== | |
39 | ||
40 | // The default number of events to cache | |
41 | public static final int DEFAULT_CACHE_SIZE = 1000; | |
8c8bf09f | 42 | |
165c977c | 43 | // ======================================================================== |
8c8bf09f | 44 | // Attributes |
165c977c | 45 | // ======================================================================== |
8c8bf09f | 46 | |
62d1696a FC |
47 | // The stream name |
48 | private final String fName; | |
49 | ||
50 | // The stream parser | |
51 | private final ITmfEventParser fParser; | |
52 | ||
53 | // The cache size | |
54 | private final int fCacheSize; | |
55 | ||
56 | // The set of event stream checkpoints (for random access) | |
57 | private Vector<TmfStreamCheckpoint> fCheckpoints = new Vector<TmfStreamCheckpoint>(); | |
58 | ||
59 | // The number of events collected | |
60 | private int fNbEvents = 0; | |
61 | ||
62 | // The time span of the event stream | |
63 | private TmfTimeRange fTimeRange = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigBang); | |
64 | ||
165c977c | 65 | // ======================================================================== |
50adc88e | 66 | // Constructors |
165c977c | 67 | // ======================================================================== |
8c8bf09f | 68 | |
62d1696a FC |
69 | /** |
70 | * @param filename | |
71 | * @param parser | |
72 | * @param cacheSize | |
73 | * @throws FileNotFoundException | |
74 | */ | |
75 | protected TmfTrace(String filename, ITmfEventParser parser, int cacheSize) throws FileNotFoundException { | |
76 | fName = filename; | |
77 | fParser = parser; | |
78 | fCacheSize = cacheSize; | |
8c8bf09f ASL |
79 | } |
80 | ||
62d1696a FC |
81 | /** |
82 | * @param filename | |
83 | * @param parser | |
84 | * @throws FileNotFoundException | |
85 | */ | |
86 | protected TmfTrace(String filename, ITmfEventParser parser) throws FileNotFoundException { | |
87 | this(filename, parser, DEFAULT_CACHE_SIZE); | |
8c8bf09f ASL |
88 | } |
89 | ||
165c977c | 90 | // ======================================================================== |
8c8bf09f | 91 | // Accessors |
165c977c | 92 | // ======================================================================== |
8c8bf09f | 93 | |
62d1696a FC |
94 | /** |
95 | * @return | |
96 | */ | |
97 | public int getCacheSize() { | |
98 | return fCacheSize; | |
8c8bf09f ASL |
99 | } |
100 | ||
62d1696a FC |
101 | /** |
102 | * @return | |
103 | */ | |
104 | public String getName() { | |
105 | return fName; | |
8c8bf09f ASL |
106 | } |
107 | ||
62d1696a FC |
108 | /* (non-Javadoc) |
109 | * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents() | |
110 | */ | |
111 | public int getNbEvents() { | |
112 | return fNbEvents; | |
8c8bf09f ASL |
113 | } |
114 | ||
62d1696a FC |
115 | /* (non-Javadoc) |
116 | * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange() | |
117 | */ | |
8c8bf09f | 118 | public TmfTimeRange getTimeRange() { |
62d1696a | 119 | return fTimeRange; |
8c8bf09f ASL |
120 | } |
121 | ||
62d1696a FC |
122 | /* (non-Javadoc) |
123 | * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getIndex(org.eclipse.linuxtools.tmf.event.TmfTimestamp) | |
124 | */ | |
125 | public int getIndex(TmfTimestamp timestamp) { | |
126 | StreamContext context = seekEvent(timestamp); | |
127 | return context.index; | |
8c8bf09f ASL |
128 | } |
129 | ||
62d1696a FC |
130 | /* (non-Javadoc) |
131 | * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimestamp(int) | |
132 | */ | |
133 | public TmfTimestamp getTimestamp(int index) { | |
134 | StreamContext context = seekEvent(index); | |
135 | TmfEvent event = peekEvent(context); | |
136 | return event.getTimestamp(); | |
82b08e62 FC |
137 | } |
138 | ||
165c977c | 139 | // ======================================================================== |
8c8bf09f | 140 | // Operators |
165c977c | 141 | // ======================================================================== |
8c8bf09f | 142 | |
62d1696a FC |
143 | public StreamContext seekEvent(TmfTimestamp timestamp) { |
144 | ||
145 | // First, find the right checkpoint | |
146 | int index = Collections.binarySearch(fCheckpoints, new TmfStreamCheckpoint(timestamp, 0)); | |
147 | ||
148 | // In the very likely event that the checkpoint was not found, bsearch | |
149 | // returns its negated would-be location (not an offset...). From that | |
150 | // index, we can then position the stream and get the event. | |
151 | if (index < 0) { | |
152 | index = Math.max(0, -(index + 2)); | |
153 | } | |
154 | ||
155 | // Position the stream at the checkpoint | |
156 | Object location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null; | |
157 | StreamContext nextEventContext; | |
158 | synchronized(this) { | |
159 | nextEventContext = seekLocation(location); | |
160 | } | |
161 | StreamContext currentEventContext = new StreamContext(nextEventContext.location, index * fCacheSize); | |
162 | ||
163 | // And get the event | |
164 | TmfEvent event = getNextEvent(nextEventContext); | |
165 | while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { | |
166 | currentEventContext.location = nextEventContext.location; | |
167 | currentEventContext.index++; | |
168 | event = getNextEvent(nextEventContext); | |
169 | } | |
170 | ||
171 | return currentEventContext; | |
172 | } | |
173 | ||
174 | public StreamContext seekEvent(int position) { | |
175 | ||
176 | // Position the stream at the previous checkpoint | |
177 | int index = position / fCacheSize; | |
178 | Object location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null; | |
179 | StreamContext nextEventContext; | |
180 | synchronized(this) { | |
181 | nextEventContext = seekLocation(location); | |
182 | } | |
183 | StreamContext currentEventContext = new StreamContext(nextEventContext); | |
184 | ||
185 | // And locate the event (if it exists) | |
186 | int current = index * fCacheSize; | |
187 | TmfEvent event = getNextEvent(nextEventContext); | |
188 | while (event != null && current < position) { | |
189 | currentEventContext.location = nextEventContext.location; | |
190 | event = getNextEvent(nextEventContext); | |
191 | current++; | |
165c977c | 192 | } |
62d1696a FC |
193 | |
194 | return currentEventContext; | |
8c8bf09f ASL |
195 | } |
196 | ||
62d1696a FC |
197 | public TmfEvent peekEvent(StreamContext context) { |
198 | StreamContext ctx = new StreamContext(context); | |
199 | return getNextEvent(ctx); | |
200 | } | |
82b08e62 | 201 | |
62d1696a FC |
202 | public TmfEvent getEvent(StreamContext context, TmfTimestamp timestamp) { |
203 | ||
204 | // Position the stream and update the context object | |
205 | StreamContext ctx = seekEvent(timestamp); | |
206 | context.location = ctx.location; | |
207 | ||
208 | return getNextEvent(context); | |
82b08e62 | 209 | } |
8c8bf09f | 210 | |
62d1696a | 211 | public TmfEvent getEvent(StreamContext context, int position) { |
8c8bf09f | 212 | |
62d1696a FC |
213 | // Position the stream and update the context object |
214 | StreamContext ctx = seekEvent(position); | |
215 | context.location = ctx.location; | |
165c977c | 216 | |
62d1696a FC |
217 | return getNextEvent(context); |
218 | } | |
165c977c | 219 | |
62d1696a FC |
220 | public synchronized TmfEvent getNextEvent(StreamContext context) { |
221 | try { | |
222 | seekLocation(context.location); | |
223 | TmfEvent event = fParser.getNextEvent(this); | |
224 | context.location = getCurrentLocation(); | |
225 | return event; | |
226 | } catch (IOException e) { | |
227 | e.printStackTrace(); | |
228 | } | |
229 | return null; | |
8c8bf09f ASL |
230 | } |
231 | ||
62d1696a FC |
232 | private void notifyListeners(TmfTimeRange range) { |
233 | TmfSignalManager.dispatchSignal(new TmfStreamUpdatedSignal(this, this, range)); | |
234 | } | |
235 | ||
8c8bf09f | 236 | /* (non-Javadoc) |
62d1696a | 237 | * @see org.eclipse.linuxtools.tmf.eventlog.ITmfEventStream#indexStream() |
8c8bf09f | 238 | */ |
62d1696a FC |
239 | public void indexStream(boolean waitForCompletion) { |
240 | IndexingJob job = new IndexingJob(fName); | |
241 | job.schedule(); | |
242 | if (waitForCompletion) { | |
243 | try { | |
244 | job.join(); | |
245 | } catch (InterruptedException e) { | |
246 | // TODO Auto-generated catch block | |
247 | e.printStackTrace(); | |
248 | } | |
249 | } | |
250 | } | |
251 | ||
252 | private class IndexingJob extends Job { | |
253 | ||
254 | public IndexingJob(String name) { | |
255 | super(name); | |
256 | } | |
257 | ||
258 | /* (non-Javadoc) | |
259 | * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) | |
260 | */ | |
261 | @Override | |
262 | protected IStatus run(IProgressMonitor monitor) { | |
263 | ||
264 | int nbEvents = 0; | |
265 | TmfTimestamp startTime = new TmfTimestamp(); | |
266 | TmfTimestamp lastTime = new TmfTimestamp(); | |
267 | TmfTimestamp rangeStartTime = new TmfTimestamp(); | |
268 | ||
269 | monitor.beginTask("Indexing " + fName, IProgressMonitor.UNKNOWN); | |
270 | ||
271 | try { | |
272 | StreamContext nextEventContext; | |
273 | synchronized(this) { | |
274 | nextEventContext = seekLocation(null); | |
275 | } | |
276 | StreamContext currentEventContext = new StreamContext(nextEventContext); | |
277 | TmfEvent event = getNextEvent(nextEventContext); | |
278 | if (event != null) { | |
279 | startTime = event.getTimestamp(); | |
280 | lastTime = event.getTimestamp(); | |
165c977c FC |
281 | } |
282 | ||
62d1696a FC |
283 | rangeStartTime = startTime; |
284 | while (event != null) { | |
285 | lastTime = event.getTimestamp(); | |
286 | if ((nbEvents++ % fCacheSize) == 0) { | |
287 | TmfStreamCheckpoint bookmark = new TmfStreamCheckpoint(lastTime, currentEventContext.location); | |
288 | synchronized(this) { | |
289 | fCheckpoints.add(bookmark); | |
290 | fNbEvents = nbEvents; | |
291 | fTimeRange = new TmfTimeRange(startTime, lastTime); | |
292 | } | |
293 | notifyListeners(new TmfTimeRange(rangeStartTime, lastTime)); | |
294 | monitor.worked(1); | |
295 | // Check monitor *after* fCheckpoints has been updated | |
296 | if (monitor.isCanceled()) { | |
297 | return Status.CANCEL_STATUS; | |
298 | } | |
165c977c | 299 | } |
165c977c | 300 | |
62d1696a FC |
301 | currentEventContext.location = nextEventContext.location; |
302 | event = getNextEvent(nextEventContext); | |
303 | } | |
304 | } | |
305 | finally { | |
306 | synchronized(this) { | |
307 | fNbEvents = nbEvents; | |
308 | fTimeRange = new TmfTimeRange(startTime, lastTime); | |
309 | } | |
310 | notifyListeners(new TmfTimeRange(rangeStartTime, lastTime)); | |
311 | monitor.done(); | |
8c8bf09f | 312 | } |
62d1696a FC |
313 | |
314 | return Status.OK_STATUS; | |
315 | } | |
8c8bf09f ASL |
316 | } |
317 | ||
8c8bf09f | 318 | } |