Added a progress monitor for indexing job.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / trace / TmfTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
15 import java.io.File;
16 import java.io.FileNotFoundException;
17 import java.lang.reflect.InvocationTargetException;
18 import java.util.Collections;
19 import java.util.Vector;
20
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24 import org.eclipse.core.runtime.jobs.Job;
25 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
26 import org.eclipse.jface.operation.IRunnableWithProgress;
27 import org.eclipse.linuxtools.tmf.event.TmfEvent;
28 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
29 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
30 import org.eclipse.linuxtools.tmf.signal.TmfSignalManager;
31
32 /**
33 * <b><u>TmfTrace</u></b>
34 * <p>
35 * Abstract implementation of ITmfTrace. It should be sufficient to extend this
36 * class and provide implementation for <code>getCurrentLocation()</code> and
37 * <code>seekLocation()</code>, as well as a proper parser, to have a working
38 * concrete imlpementation.
39 */
40 public abstract class TmfTrace implements ITmfTrace {
41
42 // ========================================================================
43 // Constants
44 // ========================================================================
45
46 // The default number of events to cache
47 public static final int DEFAULT_PAGE_SIZE = 1000;
48
49 // ========================================================================
50 // Attributes
51 // ========================================================================
52
53 // The trace path
54 private final String fPath;
55
56 // The trace name
57 private final String fName;
58
59 // The checkpoints page size
60 private final int fPageSize;
61
62 // The checkpoints page size
63 private final boolean fIndex;
64
65 // The set of event stream checkpoints (for random access)
66 protected Vector<TmfTraceCheckpoint> fCheckpoints = new Vector<TmfTraceCheckpoint>();
67
68 // The number of events collected
69 private int fNbEvents = 0;
70
71 // The time span of the event stream
72 private TmfTimeRange fTimeRange = new TmfTimeRange(TmfTimestamp.BigBang, TmfTimestamp.BigBang);
73
74 // ========================================================================
75 // Constructors
76 // ========================================================================
77
78 /**
79 * @param name
80 * @param pageSize
81 * @param index
82 * @throws FileNotFoundException
83 */
84 protected TmfTrace(String path, int pageSize, boolean index) throws FileNotFoundException {
85 int sep = path.lastIndexOf(File.separator);
86 fName = (sep >= 0) ? path.substring(sep + 1) : path;
87 fPath = path;
88 fPageSize = pageSize;
89 fIndex = index;
90 }
91
92 /**
93 * @param name
94 * @param cacheSize
95 * @throws FileNotFoundException
96 */
97 protected TmfTrace(String name, boolean index) throws FileNotFoundException {
98 this(name, DEFAULT_PAGE_SIZE, index);
99 }
100
101 /**
102 * @param name
103 * @param cacheSize
104 * @throws FileNotFoundException
105 */
106 protected TmfTrace(String name, int pageSize) throws FileNotFoundException {
107 this(name, pageSize, false);
108 }
109
110 /**
111 * @param name
112 * @throws FileNotFoundException
113 */
114 protected TmfTrace(String name) throws FileNotFoundException {
115 this(name, DEFAULT_PAGE_SIZE, false);
116 }
117
118 // ========================================================================
119 // Accessors
120 // ========================================================================
121
122 /**
123 * @return the trace path
124 */
125 public String getPath() {
126 return fPath;
127 }
128
129 /**
130 * @return the trace name
131 */
132 public String getName() {
133 return fName;
134 }
135
136 /* (non-Javadoc)
137 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
138 */
139 public int getNbEvents() {
140 return fNbEvents;
141 }
142
143 /**
144 * @return the size of the cache
145 */
146 public int getPageSize() {
147 return fPageSize;
148 }
149
150 /* (non-Javadoc)
151 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
152 */
153 public TmfTimeRange getTimeRange() {
154 return fTimeRange;
155 }
156
157 public TmfTimestamp getStartTime() {
158 return fTimeRange.getStartTime();
159 }
160
161 public TmfTimestamp getEndTime() {
162 return fTimeRange.getEndTime();
163 }
164
165 public void setTimeRange(TmfTimeRange range) {
166 fTimeRange = range;
167 }
168
169 public void setStartTime(TmfTimestamp startTime) {
170 fTimeRange = new TmfTimeRange(startTime, fTimeRange.getEndTime());
171 }
172
173 public void setEndTime(TmfTimestamp endTime) {
174 fTimeRange = new TmfTimeRange(fTimeRange.getStartTime(), endTime);
175 }
176
177 /* (non-Javadoc)
178 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getIndex(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
179 */
180 public int getIndex(TmfTimestamp timestamp) {
181 TmfTraceContext context = seekEvent(timestamp);
182 return context.index;
183 }
184
185 /* (non-Javadoc)
186 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimestamp(int)
187 */
188 public TmfTimestamp getTimestamp(int index) {
189 TmfTraceContext context = seekEvent(index);
190 TmfEvent event = peekEvent(context);
191 return event.getTimestamp();
192 }
193
194 // ========================================================================
195 // Operators
196 // ========================================================================
197
198 /* (non-Javadoc)
199 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
200 */
201 public TmfTraceContext seekEvent(TmfTimestamp timestamp) {
202
203 // First, find the right checkpoint
204 int index = Collections.binarySearch(fCheckpoints, new TmfTraceCheckpoint(timestamp, 0));
205
206 // In the very likely event that the checkpoint was not found, bsearch
207 // returns its negated would-be location (not an offset...). From that
208 // index, we can then position the stream and get the event.
209 if (index < 0) {
210 index = Math.max(0, -(index + 2));
211 }
212
213 // Position the stream at the checkpoint
214 Object location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null;
215 TmfTraceContext nextEventContext;
216 synchronized(this) {
217 nextEventContext = seekLocation(location);
218 }
219 TmfTraceContext currentEventContext = new TmfTraceContext(nextEventContext.location, index * fPageSize);
220
221 // And get the event
222 TmfEvent event = getNextEvent(nextEventContext);
223 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
224 currentEventContext.location = nextEventContext.location;
225 currentEventContext.index++;
226 event = getNextEvent(nextEventContext);
227 }
228
229 return currentEventContext;
230 }
231
232 /* (non-Javadoc)
233 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
234 */
235 public TmfTraceContext seekEvent(int position) {
236
237 // Position the stream at the previous checkpoint
238 int index = position / fPageSize;
239 Object location = (index < fCheckpoints.size()) ? fCheckpoints.elementAt(index).getLocation() : null;
240 TmfTraceContext nextEventContext;
241 synchronized(this) {
242 nextEventContext = seekLocation(location);
243 }
244 TmfTraceContext currentEventContext = new TmfTraceContext(nextEventContext);
245
246 // And locate the event (if it exists)
247 int current = index * fPageSize;
248 TmfEvent event = getNextEvent(nextEventContext);
249 while (event != null && current < position) {
250 currentEventContext.location = nextEventContext.location;
251 event = getNextEvent(nextEventContext);
252 current++;
253 }
254
255 return currentEventContext;
256 }
257
258 /* (non-Javadoc)
259 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#peekEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
260 */
261 public TmfEvent peekEvent(TmfTraceContext context) {
262 TmfTraceContext ctx = new TmfTraceContext(context);
263 return getNextEvent(ctx);
264 }
265
266 /* (non-Javadoc)
267 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext, org.eclipse.linuxtools.tmf.event.TmfTimestamp)
268 */
269 public TmfEvent getEvent(TmfTraceContext context, TmfTimestamp timestamp) {
270 TmfTraceContext ctx = seekEvent(timestamp);
271 context.location = ctx.location;
272 return getNextEvent(context);
273 }
274
275 /* (non-Javadoc)
276 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext, int)
277 */
278 public TmfEvent getEvent(TmfTraceContext context, int position) {
279 TmfTraceContext ctx = seekEvent(position);
280 context.location = ctx.location;
281 return getNextEvent(context);
282 }
283
284 /* (non-Javadoc)
285 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
286 */
287 public synchronized TmfEvent getNextEvent(TmfTraceContext context) {
288 seekLocation(context.location);
289 TmfEvent event = parseNextEvent();
290 processEvent(event);
291 context.location = getCurrentLocation();
292 return event;
293 }
294
295 /**
296 * Hook for "special" processing by the extending class
297 * @param event
298 */
299 public void processEvent(TmfEvent event) {
300 // Do nothing by default
301 }
302
303 // ========================================================================
304 // Stream indexing. Essentially, parse the file asynchronously and build
305 // the checkpoints index. This index is used to quickly find an event based
306 // on a timestamp or an index.
307 // ========================================================================
308
309 public void indexStream() {
310 final IndexingJob job = new IndexingJob(fName);
311 job.schedule();
312 if (fIndex) {
313 ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
314 try {
315 dialog.run(true, true, new IRunnableWithProgress() {
316 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
317 monitor.beginTask("Indexing " + getName(), IProgressMonitor.UNKNOWN);
318 job.join();
319 monitor.done();
320 }
321 });
322 } catch (InvocationTargetException e) {
323 e.printStackTrace();
324 } catch (InterruptedException e) {
325 e.printStackTrace();
326 }
327 }
328 }
329
330 private class IndexingJob extends Job {
331
332 public IndexingJob(String name) {
333 super(name);
334 }
335
336 /* (non-Javadoc)
337 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
338 */
339 @Override
340 protected IStatus run(IProgressMonitor monitor) {
341
342 int nbEvents = 0;
343 TmfTimestamp startTime = new TmfTimestamp();
344 TmfTimestamp lastTime = new TmfTimestamp();
345 TmfTimestamp rangeStartTime = new TmfTimestamp();
346
347 monitor.beginTask("Indexing " + fName, IProgressMonitor.UNKNOWN);
348
349 try {
350 TmfTraceContext nextEventContext;
351 synchronized(this) {
352 nextEventContext = seekLocation(null);
353 }
354 TmfTraceContext currentEventContext = new TmfTraceContext(nextEventContext);
355 TmfEvent event = getNextEvent(nextEventContext);
356 if (event != null) {
357 startTime = event.getTimestamp();
358 lastTime = event.getTimestamp();
359 }
360
361 rangeStartTime = startTime;
362 while (event != null) {
363 lastTime = event.getTimestamp();
364 if ((nbEvents++ % fPageSize) == 0) {
365 TmfTraceCheckpoint bookmark = new TmfTraceCheckpoint(lastTime, currentEventContext.location);
366 synchronized(this) {
367 fCheckpoints.add(bookmark);
368 fNbEvents = nbEvents;
369 fTimeRange = new TmfTimeRange(startTime, lastTime);
370 }
371 notifyListeners(new TmfTimeRange(rangeStartTime, lastTime));
372 monitor.worked(1);
373 // Check monitor *after* fCheckpoints has been updated
374 if (monitor.isCanceled()) {
375 return Status.CANCEL_STATUS;
376 }
377 }
378
379 // Do whatever
380 processEvent(event);
381
382 currentEventContext.location = nextEventContext.location;
383 event = getNextEvent(nextEventContext);
384 }
385 }
386 finally {
387 synchronized(this) {
388 fNbEvents = nbEvents;
389 fTimeRange = new TmfTimeRange(startTime, lastTime);
390 }
391 notifyListeners(new TmfTimeRange(rangeStartTime, lastTime));
392 monitor.done();
393 }
394
395 return Status.OK_STATUS;
396 }
397 }
398
399 private void notifyListeners(TmfTimeRange range) {
400 TmfSignalManager.dispatchSignal(new TmfTraceUpdatedSignal(this, this, range));
401 }
402
403 }
This page took 0.039919 seconds and 5 git commands to generate.