1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2012 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 * Francois Chouinard - Updated as per TMF Trace Model 1.0
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.core
.trace
;
17 import java
.io
.FileNotFoundException
;
18 import java
.util
.Vector
;
20 import org
.eclipse
.core
.resources
.IProject
;
21 import org
.eclipse
.core
.resources
.IResource
;
22 import org
.eclipse
.core
.runtime
.Path
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.component
.TmfEventProvider
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfEventRequest
;
32 * <b><u>TmfTrace</u></b>
34 * Abstract implementation of ITmfTrace.
38 public abstract class TmfTrace
<T
extends ITmfEvent
> extends TmfEventProvider
<T
> implements ITmfTrace
<T
> {
40 // ------------------------------------------------------------------------
42 // ------------------------------------------------------------------------
45 * The default trace cache size
47 public static final int DEFAULT_TRACE_CACHE_SIZE
= 1000;
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
53 // The resource used for persistent properties for this trace
54 private IResource fResource
;
60 * The cache page size AND trace checkpoints interval
62 protected int fCacheSize
= DEFAULT_TRACE_CACHE_SIZE
;
64 // The set of event stream checkpoints
65 protected Vector
<TmfCheckpoint
> fCheckpoints
= new Vector
<TmfCheckpoint
>();
67 // The number of events collected
68 protected long fNbEvents
= 0;
70 // The time span of the event stream
71 private ITmfTimestamp fStartTime
= TmfTimestamp
.BIG_CRUNCH
;
72 private ITmfTimestamp fEndTime
= TmfTimestamp
.BIG_BANG
;
75 * The trace streaming interval (0 = no streaming)
77 protected long fStreamingInterval
= 0;
82 protected ITmfTraceIndexer
<ITmfTrace
<ITmfEvent
>> fIndexer
;
84 // ------------------------------------------------------------------------
86 // ------------------------------------------------------------------------
89 * The default, parameterless, constructor
91 @SuppressWarnings({ "unchecked", "rawtypes" })
94 fIndexer
= new TmfTraceIndexer(this);
98 * The standard constructor (non-live trace)
100 * @param resource the resource associated to the trace
101 * @param type the trace event type
102 * @param path the trace path
103 * @param cacheSize the trace cache size
104 * @throws FileNotFoundException
106 protected TmfTrace(final IResource resource
, final Class
<T
> type
, final String path
, final int cacheSize
) throws FileNotFoundException
{
107 this(resource
, type
, path
, cacheSize
, 0, null);
111 * The standard constructor (live trace)
113 * @param resource the resource associated to the trace
114 * @param type the trace event type
115 * @param path the trace path
116 * @param cacheSize the trace cache size
117 * @param interval the trace streaming interval
118 * @throws FileNotFoundException
120 protected TmfTrace(final IResource resource
, final Class
<T
> type
, final String path
, final int cacheSize
, final long interval
) throws FileNotFoundException
{
121 this(resource
, type
, path
, cacheSize
, interval
, null);
125 * The full constructor
127 * @param resource the resource associated to the trace
128 * @param type the trace event type
129 * @param path the trace path
130 * @param cacheSize the trace cache size
131 * @param indexer the trace indexer
132 * @throws FileNotFoundException
134 @SuppressWarnings({ "unchecked", "rawtypes" })
135 protected TmfTrace(final IResource resource
, final Class
<T
> type
, final String path
, final int cacheSize
,
136 final long interval
, final ITmfTraceIndexer
<?
> indexer
) throws FileNotFoundException
{
138 fCacheSize
= (cacheSize
> 0) ? cacheSize
: DEFAULT_TRACE_CACHE_SIZE
;
139 fStreamingInterval
= interval
;
140 fIndexer
= (indexer
!= null) ? indexer
: new TmfTraceIndexer(this);
141 initialize(resource
, path
, type
);
147 * @param trace the original trace
149 @SuppressWarnings({ "unchecked", "rawtypes" })
150 public TmfTrace(final TmfTrace
<T
> trace
) throws FileNotFoundException
{
153 throw new IllegalArgumentException();
154 fCacheSize
= trace
.getCacheSize();
155 fStreamingInterval
= trace
.getStreamingInterval();
156 fIndexer
= new TmfTraceIndexer(this);
157 initialize(trace
.getResource(), trace
.getPath(), trace
.getType());
161 * Initialize the trace common attributes and the base component.
163 * @param resource the Eclipse resource (trace)
164 * @param path the trace path
165 * @param type the trace event type
167 * @throws FileNotFoundException
169 protected void initialize(final IResource resource
, final String path
, final Class
<T
> type
) throws FileNotFoundException
{
171 throw new FileNotFoundException();
173 fResource
= resource
;
174 String traceName
= (resource
!= null) ? resource
.getName() : null;
175 // If no resource was provided, extract the display name the trace path
176 if (traceName
== null) {
177 final int sep
= path
.lastIndexOf(Path
.SEPARATOR
);
178 traceName
= (sep
>= 0) ? path
.substring(sep
+ 1) : path
;
180 super.init(traceName
, type
);
183 // ------------------------------------------------------------------------
184 // ITmfTrace - Initializers
185 // ------------------------------------------------------------------------
188 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#initTrace(org.eclipse.core.resources.IResource, java.lang.String, java.lang.Class)
191 public void initTrace(final IResource resource
, final String path
, final Class
<T
> type
) throws FileNotFoundException
{
192 initialize(resource
, path
, type
);
193 fIndexer
.buildIndex(false);
197 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)
199 * Default validation: make sure the trace file exists.
202 public boolean validate(final IProject project
, final String path
) {
203 final File file
= new File(path
);
204 return file
.exists();
207 // ------------------------------------------------------------------------
208 // ITmfTrace - Basic getters
209 // ------------------------------------------------------------------------
212 * @see org.eclipse.linuxtools.tmf.core.component.TmfDataProvider#getType()
215 @SuppressWarnings("unchecked")
216 public Class
<T
> getType() {
217 return (Class
<T
>) super.getType();
221 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
224 public IResource
getResource() {
229 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getPath()
232 public String
getPath() {
237 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getIndexPageSize()
240 public int getCacheSize() {
245 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStreamingInterval()
248 public long getStreamingInterval() {
249 return fStreamingInterval
;
252 // ------------------------------------------------------------------------
253 // ITmfTrace - Trace characteristics getters
254 // ------------------------------------------------------------------------
257 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNbEvents()
260 public long getNbEvents() {
265 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getTimeRange()
268 public TmfTimeRange
getTimeRange() {
269 return new TmfTimeRange(fStartTime
, fEndTime
);
273 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStartTime()
276 public ITmfTimestamp
getStartTime() {
277 return fStartTime
.clone();
281 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getEndTime()
284 public ITmfTimestamp
getEndTime() {
285 return fEndTime
.clone();
288 // ------------------------------------------------------------------------
289 // Convenience setters
290 // ------------------------------------------------------------------------
293 * Update the trace events time range
295 * @param range the new time range
297 protected void setTimeRange(final TmfTimeRange range
) {
298 fStartTime
= range
.getStartTime().clone();
299 fEndTime
= range
.getEndTime().clone();
303 * Update the trace chronologically first event timestamp
305 * @param startTime the new first event timestamp
307 protected void setStartTime(final ITmfTimestamp startTime
) {
308 fStartTime
= startTime
.clone();
312 * Update the trace chronologically last event timestamp
314 * @param endTime the new last event timestamp
316 protected void setEndTime(final ITmfTimestamp endTime
) {
317 fEndTime
= endTime
.clone();
321 * Update the trace streaming interval
323 * @param interval the new trace streaming interval
325 protected void setStreamingInterval(final long interval
) {
326 fStreamingInterval
= (interval
> 0) ? interval
: 0;
329 // ------------------------------------------------------------------------
330 // ITmfTrace - Seek operations (returning a reading context)
331 // ------------------------------------------------------------------------
334 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
337 public synchronized ITmfContext
seekEvent(final ITmfTimestamp timestamp
) {
339 // A null timestamp indicates to seek the first event
340 if (timestamp
== null)
341 return seekLocation(null);
343 // Position the trace at the checkpoint
344 final ITmfContext context
= fIndexer
.seekIndex(timestamp
);
346 // And locate the requested event context
347 final ITmfContext nextEventContext
= context
.clone(); // Must use clone() to get the right subtype...
348 ITmfEvent event
= getNextEvent(nextEventContext
);
349 while (event
!= null && event
.getTimestamp().compareTo(timestamp
, false) < 0) {
350 context
.setLocation(nextEventContext
.getLocation().clone());
351 context
.increaseRank();
352 event
= getNextEvent(nextEventContext
);
358 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(long)
361 public synchronized ITmfContext
seekEvent(final long rank
) {
363 // A rank <= 0 indicates to seek the first event
365 return seekLocation(null);
367 // Position the trace at the checkpoint
368 final ITmfContext context
= fIndexer
.seekIndex(rank
);
370 // And locate the requested event context
371 long pos
= context
.getRank();
373 ITmfEvent event
= getNextEvent(context
);
374 while (event
!= null && ++pos
< rank
) {
375 event
= getNextEvent(context
);
381 // ------------------------------------------------------------------------
382 // ITmfTrace - Read operations (returning an actual event)
383 // ------------------------------------------------------------------------
386 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
389 public synchronized ITmfEvent
getNextEvent(final ITmfContext context
) {
390 // parseEvent() does not update the context
391 final ITmfEvent event
= parseEvent(context
);
393 updateIndex(context
, context
.getRank(), event
.getTimestamp());
394 context
.setLocation(getCurrentLocation());
395 context
.increaseRank();
402 * Hook for special processing by the concrete class (called by
407 protected void processEvent(final ITmfEvent event
) {
408 // Do nothing by default
411 protected synchronized void updateIndex(final ITmfContext context
, final long rank
, final ITmfTimestamp timestamp
) {
412 if (fStartTime
.compareTo(timestamp
, false) > 0) {
413 fStartTime
= timestamp
;
415 if (fEndTime
.compareTo(timestamp
, false) < 0) {
416 fEndTime
= timestamp
;
418 if (context
.hasValidRank()) {
419 if (fNbEvents
<= rank
) {
420 fNbEvents
= rank
+ 1;
422 // Build the index as we go along
423 if ((rank
% fCacheSize
) == 0) {
424 // Determine the table position
425 final long position
= rank
/ fCacheSize
;
426 // Add new entry at proper location (if empty)
427 if (fCheckpoints
.size() == position
) {
428 final ITmfLocation
<?
> location
= context
.getLocation().clone();
429 fCheckpoints
.add(new TmfCheckpoint(timestamp
.clone(), location
));
430 // System.out.println(getName() + "[" + (fCheckpoints.size() + "] " + timestamp + ", " + location.toString());
436 // ------------------------------------------------------------------------
438 // ------------------------------------------------------------------------
441 public ITmfContext
armRequest(final ITmfDataRequest
<T
> request
) {
442 if (request
instanceof ITmfEventRequest
<?
>
443 && !TmfTimestamp
.BIG_BANG
.equals(((ITmfEventRequest
<T
>) request
).getRange().getStartTime())
444 && request
.getIndex() == 0) {
445 final ITmfContext context
= seekEvent(((ITmfEventRequest
<T
>) request
).getRange().getStartTime());
446 ((ITmfEventRequest
<T
>) request
).setStartIndex((int) context
.getRank());
450 return seekEvent(request
.getIndex());
454 * Return the next piece of data based on the context supplied. The context
455 * would typically be updated for the subsequent read.
458 * @return the event referred to by context
461 @SuppressWarnings("unchecked")
462 public T
getNext(final ITmfContext context
) {
463 if (context
instanceof TmfContext
)
464 return (T
) getNextEvent(context
);
469 // ------------------------------------------------------------------------
471 // ------------------------------------------------------------------------
474 @SuppressWarnings("nls")
475 public String
toString() {
476 return "TmfTrace [fPath=" + fPath
+ ", fCacheSize=" + fCacheSize
477 + ", fNbEvents=" + fNbEvents
+ ", fStartTime=" + fStartTime
478 + ", fEndTime=" + fEndTime
+ ", fStreamingInterval=" + fStreamingInterval
+ "]";