1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 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
.util
.Collections
;
18 import java
.util
.Vector
;
20 import org
.eclipse
.linuxtools
.tmf
.component
.TmfEventProvider
;
21 import org
.eclipse
.linuxtools
.tmf
.event
.TmfEvent
;
22 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
23 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
24 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfDataRequest
;
25 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfEventRequest
;
28 * <b><u>TmfTrace</u></b>
30 * Abstract implementation of ITmfTrace. It should be sufficient to extend this
31 * class and provide implementation for <code>getCurrentLocation()</code> and
32 * <code>seekLocation()</code>, as well as a proper parser, to have a working
33 * concrete implementation.
35 * Note: The notion of event rank is still under heavy discussion. Although
36 * used by the Events View and probably useful in the general case, there
37 * is no easy way to implement it for LTTng (actually a strong case is being
38 * made that this is useless).
40 * That it is not supported by LTTng does by no mean indicate that it is not
41 * useful for (just about) every other tracing tool. Therefore, this class
42 * provides a minimal (and partial) implementation of rank. However, the current
43 * implementation should not be relied on in the general case.
45 * TODO: Add support for live streaming (notifications, incremental indexing, ...)
47 public abstract class TmfTrace
<T
extends TmfEvent
> extends TmfEventProvider
<T
> implements ITmfTrace
, Cloneable
{
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
53 // The default number of events to cache
54 // TODO: Make the DEFAULT_CACHE_SIZE a preference
55 public static final int DEFAULT_CACHE_SIZE
= 1000;
57 // ------------------------------------------------------------------------
59 // ------------------------------------------------------------------------
62 private final String fPath
;
64 // The cache page size AND checkpoints interval
65 protected int fIndexPageSize
;
67 // The set of event stream checkpoints (for random access)
68 protected Vector
<TmfCheckpoint
> fCheckpoints
= new Vector
<TmfCheckpoint
>();
70 // The number of events collected
71 protected long fNbEvents
= 0;
73 // The time span of the event stream
74 private TmfTimeRange fTimeRange
= new TmfTimeRange(TmfTimestamp
.BigBang
, TmfTimestamp
.BigBang
);
76 // ------------------------------------------------------------------------
78 // ------------------------------------------------------------------------
82 * @throws FileNotFoundException
84 protected TmfTrace(String name
, Class
<T
> type
, String path
) throws FileNotFoundException
{
85 this(name
, type
, path
, DEFAULT_CACHE_SIZE
);
91 * @throws FileNotFoundException
93 protected TmfTrace(String name
, Class
<T
> type
, String path
, int cacheSize
) throws FileNotFoundException
{
95 int sep
= path
.lastIndexOf(File
.separator
);
96 String simpleName
= (sep
>= 0) ? path
.substring(sep
+ 1) : path
;
99 fIndexPageSize
= (cacheSize
> 0) ? cacheSize
: DEFAULT_CACHE_SIZE
;
103 } catch (CloneNotSupportedException e
) {
109 * @see java.lang.Object#clone()
111 @SuppressWarnings("unchecked")
113 public TmfTrace
<T
> clone() throws CloneNotSupportedException
{
114 TmfTrace
<T
> clone
= (TmfTrace
<T
>) super.clone();
115 clone
.fCheckpoints
= (Vector
<TmfCheckpoint
>) fCheckpoints
.clone();
116 clone
.fTimeRange
= new TmfTimeRange(fTimeRange
);
120 // ------------------------------------------------------------------------
122 // ------------------------------------------------------------------------
125 * @return the trace path
127 public String
getPath() {
132 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
134 public long getNbEvents() {
139 * @return the size of the cache
141 public int getCacheSize() {
142 return fIndexPageSize
;
146 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
148 public TmfTimeRange
getTimeRange() {
153 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
155 public TmfTimestamp
getStartTime() {
156 return fTimeRange
.getStartTime();
160 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
162 public TmfTimestamp
getEndTime() {
163 return fTimeRange
.getEndTime();
166 @SuppressWarnings("unchecked")
167 public Vector
<TmfCheckpoint
> getCheckpoints() {
168 return (Vector
<TmfCheckpoint
>) fCheckpoints
.clone();
171 // ------------------------------------------------------------------------
173 // ------------------------------------------------------------------------
175 protected void setTimeRange(TmfTimeRange range
) {
179 protected void setStartTime(TmfTimestamp startTime
) {
180 fTimeRange
= new TmfTimeRange(startTime
, fTimeRange
.getEndTime());
183 protected void setEndTime(TmfTimestamp endTime
) {
184 fTimeRange
= new TmfTimeRange(fTimeRange
.getStartTime(), endTime
);
187 // ------------------------------------------------------------------------
189 // ------------------------------------------------------------------------
192 public ITmfContext
armRequest(ITmfDataRequest
<T
> request
) {
193 if (request
instanceof ITmfEventRequest
<?
>) {
194 return seekEvent(((ITmfEventRequest
<T
>) request
).getRange().getStartTime());
196 return seekEvent(request
.getIndex());
200 * Return the next piece of data based on the context supplied. The context
201 * would typically be updated for the subsequent read.
206 @SuppressWarnings("unchecked")
208 public T
getNext(ITmfContext context
) {
209 if (context
instanceof TmfContext
) {
210 return (T
) getNextEvent((TmfContext
) context
);
215 // ------------------------------------------------------------------------
217 // ------------------------------------------------------------------------
220 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp)
222 public TmfContext
seekEvent(TmfTimestamp timestamp
) {
224 if (timestamp
== null) {
225 timestamp
= TmfTimestamp
.BigBang
;
228 // First, find the right checkpoint
229 int index
= Collections
.binarySearch(fCheckpoints
, new TmfCheckpoint(timestamp
, null));
231 // In the very likely case that the checkpoint was not found, bsearch
232 // returns its negated would-be location (not an offset...). From that
233 // index, we can then position the stream and get the event.
235 index
= Math
.max(0, -(index
+ 2));
238 // Position the stream at the checkpoint
239 ITmfLocation
<?
> location
;
240 synchronized (fCheckpoints
) {
241 if (fCheckpoints
.size() > 0) {
242 if (index
>= fCheckpoints
.size()) {
243 index
= fCheckpoints
.size() - 1;
245 location
= fCheckpoints
.elementAt(index
).getLocation();
251 TmfContext context
= seekLocation(location
);
252 context
.setRank(index
* fIndexPageSize
);
254 // And locate the event
255 TmfContext nextEventContext
= context
.clone(); // Must use clone() to get the right subtype...
256 TmfEvent event
= getNextEvent(nextEventContext
);
257 while (event
!= null && event
.getTimestamp().compareTo(timestamp
, false) < 0) {
258 context
.setLocation(nextEventContext
.getLocation().clone());
259 context
.updateRank(1);
260 event
= getNextEvent(nextEventContext
);
267 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int)
269 public TmfContext
seekEvent(long rank
) {
271 // Position the stream at the previous checkpoint
272 int index
= (int) rank
/ fIndexPageSize
;
273 ITmfLocation
<?
> location
;
274 synchronized (fCheckpoints
) {
275 if (fCheckpoints
.size() == 0) {
279 if (index
>= fCheckpoints
.size()) {
280 index
= fCheckpoints
.size() - 1;
282 location
= fCheckpoints
.elementAt(index
).getLocation();
286 TmfContext context
= seekLocation(location
);
287 long pos
= index
* fIndexPageSize
;
288 context
.setRank(pos
);
291 TmfEvent event
= getNextEvent(context
);
292 while (event
!= null && ++pos
< rank
) {
293 event
= getNextEvent(context
);
301 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.linuxtools.tmf.trace.ITmfTrace.TraceContext)
303 public synchronized TmfEvent
getNextEvent(TmfContext context
) {
304 // parseEvent() does not update the context
305 TmfEvent event
= parseEvent(context
);
307 context
.setLocation(getCurrentLocation());
308 updateIndex(context
, context
.getRank(), event
.getTimestamp());
309 context
.updateRank(1);
315 public synchronized void updateIndex(ITmfContext context
, long rank
, TmfTimestamp timestamp
) {
316 // Build the index as we go along
317 if (context
.isValidRank() && (rank
% fIndexPageSize
) == 0) {
318 // Determine the table position
319 long position
= rank
/ fIndexPageSize
;
320 // Add new entry at proper location (if empty)
321 if (fCheckpoints
.size() == position
) {
322 ITmfLocation
<?
> location
= getCurrentLocation().clone();
323 fCheckpoints
.add(new TmfCheckpoint(timestamp
, location
));
324 // System.out.println(getName() + "[" + (fCheckpoints.size() - 1) + "] " + timestamp + ", " + location.toString());
330 * Hook for "special" processing by the concrete class
331 * (called by getNextEvent())
335 protected void processEvent(TmfEvent event
) {
336 // Do nothing by default
340 * To be implemented by the concrete class
342 public abstract TmfContext
seekLocation(ITmfLocation
<?
> location
);
343 public abstract ITmfLocation
<?
> getCurrentLocation();
344 public abstract TmfEvent
parseEvent(TmfContext context
);
346 // ------------------------------------------------------------------------
348 // ------------------------------------------------------------------------
351 * @see java.lang.Object#toString()
354 public String
toString() {
355 return "[TmfTrace (" + getName() + ")]";