1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
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
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.trace
;
16 import java
.io
.FileNotFoundException
;
17 import java
.lang
.reflect
.InvocationTargetException
;
18 import java
.util
.Collections
;
19 import java
.util
.Vector
;
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
;
33 * <b><u>TmfTrace</u></b>
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.
40 public abstract class TmfTrace
implements ITmfTrace
{
42 // ========================================================================
44 // ========================================================================
46 // The default number of events to cache
47 public static final int DEFAULT_PAGE_SIZE
= 1000;
49 // ========================================================================
51 // ========================================================================
54 private final String fPath
;
57 private final String fName
;
59 // The checkpoints page size
60 private final int fPageSize
;
62 // The checkpoints page size
63 private final boolean fIndex
;
65 // The set of event stream checkpoints (for random access)
66 protected Vector
<TmfTraceCheckpoint
> fCheckpoints
= new Vector
<TmfTraceCheckpoint
>();
68 // The number of events collected
69 private int fNbEvents
= 0;
71 // The time span of the event stream
72 private TmfTimeRange fTimeRange
= new TmfTimeRange(TmfTimestamp
.BigBang
, TmfTimestamp
.BigBang
);
74 // ========================================================================
76 // ========================================================================
82 * @throws FileNotFoundException
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
;
95 * @throws FileNotFoundException
97 protected TmfTrace(String name
, boolean index
) throws FileNotFoundException
{
98 this(name
, DEFAULT_PAGE_SIZE
, index
);
104 * @throws FileNotFoundException
106 protected TmfTrace(String name
, int pageSize
) throws FileNotFoundException
{
107 this(name
, pageSize
, false);
112 * @throws FileNotFoundException
114 protected TmfTrace(String name
) throws FileNotFoundException
{
115 this(name
, DEFAULT_PAGE_SIZE
, false);
118 // ========================================================================
120 // ========================================================================
123 * @return the trace path
125 public String
getPath() {
130 * @return the trace name
132 public String
getName() {
137 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
139 public int getNbEvents() {
144 * @return the size of the cache
146 public int getPageSize() {
151 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
153 public TmfTimeRange
getTimeRange() {
157 public TmfTimestamp
getStartTime() {
158 return fTimeRange
.getStartTime();
161 public TmfTimestamp
getEndTime() {
162 return fTimeRange
.getEndTime();
165 public void setTimeRange(TmfTimeRange range
) {
169 public void setStartTime(TmfTimestamp startTime
) {
170 fTimeRange
= new TmfTimeRange(startTime
, fTimeRange
.getEndTime());
173 public void setEndTime(TmfTimestamp endTime
) {
174 fTimeRange
= new TmfTimeRange(fTimeRange
.getStartTime(), endTime
);
178 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getIndex(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
180 public int getIndex(TmfTimestamp timestamp
) {
181 TmfTraceContext context
= seekEvent(timestamp
);
182 return context
.index
;
186 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimestamp(int)
188 public TmfTimestamp
getTimestamp(int index
) {
189 TmfTraceContext context
= seekEvent(index
);
190 TmfEvent event
= peekEvent(context
);
191 return event
.getTimestamp();
194 // ========================================================================
196 // ========================================================================
199 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
201 public TmfTraceContext
seekEvent(TmfTimestamp timestamp
) {
203 // First, find the right checkpoint
204 int index
= Collections
.binarySearch(fCheckpoints
, new TmfTraceCheckpoint(timestamp
, 0));
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.
210 index
= Math
.max(0, -(index
+ 2));
213 // Position the stream at the checkpoint
214 Object location
= (index
< fCheckpoints
.size()) ? fCheckpoints
.elementAt(index
).getLocation() : null;
215 TmfTraceContext nextEventContext
;
217 nextEventContext
= seekLocation(location
);
219 TmfTraceContext currentEventContext
= new TmfTraceContext(nextEventContext
.location
, index
* fPageSize
);
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
);
229 return currentEventContext
;
233 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
235 public TmfTraceContext
seekEvent(int position
) {
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
;
242 nextEventContext
= seekLocation(location
);
244 TmfTraceContext currentEventContext
= new TmfTraceContext(nextEventContext
);
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
);
255 return currentEventContext
;
259 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#peekEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
261 public TmfEvent
peekEvent(TmfTraceContext context
) {
262 TmfTraceContext ctx
= new TmfTraceContext(context
);
263 return getNextEvent(ctx
);
267 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext, org.eclipse.linuxtools.tmf.event.TmfTimestamp)
269 public TmfEvent
getEvent(TmfTraceContext context
, TmfTimestamp timestamp
) {
270 TmfTraceContext ctx
= seekEvent(timestamp
);
271 context
.location
= ctx
.location
;
272 return getNextEvent(context
);
276 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext, int)
278 public TmfEvent
getEvent(TmfTraceContext context
, int position
) {
279 TmfTraceContext ctx
= seekEvent(position
);
280 context
.location
= ctx
.location
;
281 return getNextEvent(context
);
285 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
287 public synchronized TmfEvent
getNextEvent(TmfTraceContext context
) {
288 seekLocation(context
.location
);
289 TmfEvent event
= parseNextEvent();
291 context
.location
= getCurrentLocation();
296 * Hook for "special" processing by the extending class
299 public void processEvent(TmfEvent event
) {
300 // Do nothing by default
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 // ========================================================================
309 public void indexStream() {
310 final IndexingJob job
= new IndexingJob(fName
);
313 ProgressMonitorDialog dialog
= new ProgressMonitorDialog(null);
315 dialog
.run(true, true, new IRunnableWithProgress() {
316 public void run(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
317 monitor
.beginTask("Indexing " + getName(), IProgressMonitor
.UNKNOWN
);
322 } catch (InvocationTargetException e
) {
324 } catch (InterruptedException e
) {
330 private class IndexingJob
extends Job
{
332 public IndexingJob(String name
) {
337 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
340 protected IStatus
run(IProgressMonitor monitor
) {
343 TmfTimestamp startTime
= new TmfTimestamp();
344 TmfTimestamp lastTime
= new TmfTimestamp();
345 TmfTimestamp rangeStartTime
= new TmfTimestamp();
347 monitor
.beginTask("Indexing " + fName
, IProgressMonitor
.UNKNOWN
);
350 TmfTraceContext nextEventContext
;
352 nextEventContext
= seekLocation(null);
354 TmfTraceContext currentEventContext
= new TmfTraceContext(nextEventContext
);
355 TmfEvent event
= getNextEvent(nextEventContext
);
357 startTime
= event
.getTimestamp();
358 lastTime
= event
.getTimestamp();
361 rangeStartTime
= startTime
;
362 while (event
!= null) {
363 lastTime
= event
.getTimestamp();
364 if ((nbEvents
++ % fPageSize
) == 0) {
365 TmfTraceCheckpoint bookmark
= new TmfTraceCheckpoint(lastTime
, currentEventContext
.location
);
367 fCheckpoints
.add(bookmark
);
368 fNbEvents
= nbEvents
;
369 fTimeRange
= new TmfTimeRange(startTime
, lastTime
);
371 notifyListeners(new TmfTimeRange(rangeStartTime
, lastTime
));
373 // Check monitor *after* fCheckpoints has been updated
374 if (monitor
.isCanceled()) {
375 return Status
.CANCEL_STATUS
;
382 currentEventContext
.location
= nextEventContext
.location
;
383 event
= getNextEvent(nextEventContext
);
388 fNbEvents
= nbEvents
;
389 fTimeRange
= new TmfTimeRange(startTime
, lastTime
);
391 notifyListeners(new TmfTimeRange(rangeStartTime
, lastTime
));
395 return Status
.OK_STATUS
;
399 private void notifyListeners(TmfTimeRange range
) {
400 TmfSignalManager
.dispatchSignal(new TmfTraceUpdatedSignal(this, this, range
));