Fix seekEvent() problem and augment TmfExperimentTest
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2012 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 * Francois Chouinard - Updated as per TMF Trace Model 1.0
12 *******************************************************************************/
13
14 package org.eclipse.linuxtools.tmf.core.trace;
15
16 import java.io.File;
17
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.runtime.IPath;
20 import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider;
21 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
22 import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
23 import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
24 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
25 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
26 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
27 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
28
29 /**
30 * Abstract implementation of ITmfTrace.
31 * <p>
32 * Since the concept of 'location' is trace specific, the concrete classes have
33 * to provide the related methods, namely:
34 * <ul>
35 * <li> public ITmfLocation<?> getCurrentLocation()
36 * <li> public double getLocationRatio(ITmfLocation<?> location)
37 * <li> public ITmfContext seekEvent(ITmfLocation<?> location)
38 * <li> public ITmfContext seekEvent(double ratio)
39 * <li> public boolean validate(IProject project, String path)
40 * </ul>
41 * A concrete trace must provide its corresponding parser. A common way to
42 * accomplish this is by making the concrete class extend TmfTrace and
43 * implement ITmfEventParser.
44 * <p>
45 * The concrete class can either specify its own indexer or use the provided
46 * TmfCheckpointIndexer (default). In this case, the trace cache size will be
47 * used as checkpoint interval.
48 *
49 * @version 1.0
50 * @author Francois Chouinard
51 *
52 * @see ITmfEvent
53 * @see ITmfTraceIndexer
54 * @see ITmfEventParser
55 */
56 public abstract class TmfTrace<T extends ITmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T> {
57
58 // ------------------------------------------------------------------------
59 // Attributes
60 // ------------------------------------------------------------------------
61
62 // The resource used for persistent properties for this trace
63 private IResource fResource;
64
65 // The trace path
66 private String fPath;
67
68 // The trace cache page size
69 private int fCacheSize = ITmfTrace.DEFAULT_TRACE_CACHE_SIZE;
70
71 // The number of events collected (so far)
72 private long fNbEvents = 0;
73
74 // The time span of the event stream
75 private ITmfTimestamp fStartTime = TmfTimestamp.BIG_CRUNCH;
76 private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG;
77
78 // The trace streaming interval (0 = no streaming)
79 private long fStreamingInterval = 0;
80
81 // The trace indexer
82 private ITmfTraceIndexer<ITmfTrace<ITmfEvent>> fIndexer;
83
84 // The trace parser
85 private ITmfEventParser<T> fParser;
86
87 // ------------------------------------------------------------------------
88 // Construction
89 // ------------------------------------------------------------------------
90
91 /**
92 * The default, parameterless, constructor
93 */
94 public TmfTrace() {
95 super();
96 }
97
98 /**
99 * The standard constructor (non-live trace). Applicable when the trace
100 * implements its own parser and if at checkpoint-based index is OK.
101 *
102 * @param resource the resource associated to the trace
103 * @param type the trace event type
104 * @param path the trace path
105 * @param cacheSize the trace cache size
106 * @throws TmfTraceException
107 */
108 protected TmfTrace(final IResource resource, final Class<T> type, final String path, final int cacheSize) throws TmfTraceException {
109 this(resource, type, path, cacheSize, 0);
110 }
111
112 /**
113 * The standard constructor (live trace). Applicable when the trace
114 * implements its own parser and if at checkpoint-based index is OK.
115 *
116 * @param resource the resource associated to the trace
117 * @param type the trace event type
118 * @param path the trace path
119 * @param cacheSize the trace cache size
120 * @param interval the trace streaming interval
121 * @throws TmfTraceException
122 */
123 protected TmfTrace(final IResource resource, final Class<T> type, final String path, final int cacheSize, final long interval) throws TmfTraceException {
124 this(resource, type, path, cacheSize, interval, null);
125 }
126
127 /**
128 * The 'non-default indexer' constructor. Allows to provide a trace
129 * specific indexer.
130 *
131 * @param resource the resource associated to the trace
132 * @param type the trace event type
133 * @param path the trace path
134 * @param cacheSize the trace cache size
135 * @param indexer the trace indexer
136 * @throws TmfTraceException
137 */
138 protected TmfTrace(final IResource resource, final Class<T> type, final String path, final int cacheSize,
139 final long interval, final ITmfTraceIndexer<?> indexer) throws TmfTraceException {
140 this(resource, type, path, cacheSize, interval, indexer, null);
141 }
142
143 /**
144 * The full constructor where trace specific indexer/parser are provided.
145 *
146 * @param resource the resource associated to the trace
147 * @param type the trace event type
148 * @param path the trace path
149 * @param cacheSize the trace cache size
150 * @param indexer the trace indexer
151 * @param parser the trace event parser
152 * @throws TmfTraceException
153 */
154 @SuppressWarnings({ "unchecked", "rawtypes" })
155 protected TmfTrace(final IResource resource, final Class<T> type, final String path, final int cacheSize,
156 final long interval, final ITmfTraceIndexer<?> indexer, final ITmfEventParser<T> parser) throws TmfTraceException {
157 super();
158 fCacheSize = (cacheSize > 0) ? cacheSize : ITmfTrace.DEFAULT_TRACE_CACHE_SIZE;
159 fStreamingInterval = interval;
160 fIndexer = (indexer != null) ? indexer : new TmfCheckpointIndexer(this, fCacheSize);
161 fParser = parser;
162 initialize(resource, path, type);
163 }
164
165 /**
166 * Copy constructor
167 *
168 * @param trace the original trace
169 */
170 @SuppressWarnings({ "unchecked", "rawtypes" })
171 public TmfTrace(final TmfTrace<T> trace) throws TmfTraceException {
172 super();
173 if (trace == null) {
174 throw new IllegalArgumentException();
175 }
176 fCacheSize = trace.getCacheSize();
177 fStreamingInterval = trace.getStreamingInterval();
178 fIndexer = new TmfCheckpointIndexer(this);
179 fParser = trace.fParser;
180 initialize(trace.getResource(), trace.getPath(), trace.getEventType());
181 }
182
183 // ------------------------------------------------------------------------
184 // ITmfTrace - Initializers
185 // ------------------------------------------------------------------------
186
187 /* (non-Javadoc)
188 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#initTrace(org.eclipse.core.resources.IResource, java.lang.String, java.lang.Class)
189 */
190 @Override
191 @SuppressWarnings({ "unchecked", "rawtypes" })
192 public void initTrace(final IResource resource, final String path, final Class<T> type) throws TmfTraceException {
193 fIndexer = new TmfCheckpointIndexer(this, fCacheSize);
194 initialize(resource, path, type);
195 }
196
197 /**
198 * Initialize the trace common attributes and the base component.
199 *
200 * @param resource the Eclipse resource (trace)
201 * @param path the trace path
202 * @param type the trace event type
203 *
204 * @throws TmfTraceException
205 */
206 @SuppressWarnings("unchecked")
207 protected void initialize(final IResource resource, final String path, final Class<T> type) throws TmfTraceException {
208 if (path == null) {
209 throw new TmfTraceException("Invalid trace path"); //$NON-NLS-1$
210 }
211 fPath = path;
212 fResource = resource;
213 String traceName = (resource != null) ? resource.getName() : null;
214 // If no resource was provided, extract the display name the trace path
215 if (traceName == null) {
216 final int sep = path.lastIndexOf(IPath.SEPARATOR);
217 traceName = (sep >= 0) ? path.substring(sep + 1) : path;
218 }
219 if (fParser == null) {
220 if (this instanceof ITmfEventParser) {
221 fParser = (ITmfEventParser<T>) this;
222 } else {
223 throw new TmfTraceException("Invalid trace parser"); //$NON-NLS-1$
224 }
225 }
226 super.init(traceName, type);
227 }
228
229 /**
230 * Indicates if the path points to an existing file/directory
231 *
232 * @param path the path to test
233 * @return true if the file/directory exists
234 */
235 protected boolean fileExists(final String path) {
236 final File file = new File(path);
237 return file.exists();
238 }
239
240 /**
241 * Index the trace
242 *
243 * @param waitForCompletion index synchronously (true) or not (false)
244 */
245 protected void indexTrace(boolean waitForCompletion) {
246 getIndexer().buildIndex(0, TmfTimeRange.ETERNITY, waitForCompletion);
247 }
248
249 /**
250 * Clears the trace
251 */
252 @Override
253 public synchronized void dispose() {
254 // Clean up the index if applicable
255 if (getIndexer() != null) {
256 getIndexer().dispose();
257 }
258 super.dispose();
259 }
260
261 // ------------------------------------------------------------------------
262 // ITmfTrace - Basic getters
263 // ------------------------------------------------------------------------
264
265 /* (non-Javadoc)
266 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getEventType()
267 */
268 @Override
269 @SuppressWarnings("unchecked")
270 public Class<T> getEventType() {
271 return (Class<T>) super.getType();
272 }
273
274 /* (non-Javadoc)
275 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
276 */
277 @Override
278 public IResource getResource() {
279 return fResource;
280 }
281
282 /* (non-Javadoc)
283 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getPath()
284 */
285 @Override
286 public String getPath() {
287 return fPath;
288 }
289
290 /* (non-Javadoc)
291 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getIndexPageSize()
292 */
293 @Override
294 public int getCacheSize() {
295 return fCacheSize;
296 }
297
298 /* (non-Javadoc)
299 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStreamingInterval()
300 */
301 @Override
302 public long getStreamingInterval() {
303 return fStreamingInterval;
304 }
305
306 /**
307 * @return the trace indexer
308 */
309 protected ITmfTraceIndexer<ITmfTrace<ITmfEvent>> getIndexer() {
310 return fIndexer;
311 }
312
313 /**
314 * @return the trace parser
315 */
316 protected ITmfEventParser<T> getParser() {
317 return fParser;
318 }
319
320 // ------------------------------------------------------------------------
321 // ITmfTrace - Trace characteristics getters
322 // ------------------------------------------------------------------------
323
324 /* (non-Javadoc)
325 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNbEvents()
326 */
327 @Override
328 public synchronized long getNbEvents() {
329 return fNbEvents;
330 }
331
332 /* (non-Javadoc)
333 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getTimeRange()
334 */
335 @Override
336 public TmfTimeRange getTimeRange() {
337 return new TmfTimeRange(fStartTime, fEndTime);
338 }
339
340 /* (non-Javadoc)
341 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStartTime()
342 */
343 @Override
344 public ITmfTimestamp getStartTime() {
345 return fStartTime.clone();
346 }
347
348 /* (non-Javadoc)
349 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getEndTime()
350 */
351 @Override
352 public ITmfTimestamp getEndTime() {
353 return fEndTime.clone();
354 }
355
356 // ------------------------------------------------------------------------
357 // Convenience setters/getters
358 // ------------------------------------------------------------------------
359
360 /**
361 * Set the trace cache size. Must be done at initialization time.
362 *
363 * @param cacheSize The trace cache size
364 */
365 protected void setCacheSize(final int cacheSize) {
366 fCacheSize = cacheSize;
367 }
368
369 /**
370 * Set the trace known number of events. This can be quite dynamic
371 * during indexing or for live traces.
372 *
373 * @param nbEvents The number of events
374 */
375 protected synchronized void setNbEvents(final long nbEvents) {
376 fNbEvents = (nbEvents > 0) ? nbEvents : 0;
377 }
378
379 /**
380 * Update the trace events time range
381 *
382 * @param range the new time range
383 */
384 protected void setTimeRange(final TmfTimeRange range) {
385 fStartTime = range.getStartTime().clone();
386 fEndTime = range.getEndTime().clone();
387 }
388
389 /**
390 * Update the trace chronologically first event timestamp
391 *
392 * @param startTime the new first event timestamp
393 */
394 protected void setStartTime(final ITmfTimestamp startTime) {
395 fStartTime = startTime.clone();
396 }
397
398 /**
399 * Update the trace chronologically last event timestamp
400 *
401 * @param endTime the new last event timestamp
402 */
403 protected void setEndTime(final ITmfTimestamp endTime) {
404 fEndTime = endTime.clone();
405 }
406
407 /**
408 * Set the polling interval for live traces (default = 0 = no streaming).
409 *
410 * @param interval the new trace streaming interval
411 */
412 protected void setStreamingInterval(final long interval) {
413 fStreamingInterval = (interval > 0) ? interval : 0;
414 }
415
416 /**
417 * Set the trace indexer. Must be done at initialization time.
418 *
419 * @param indexer the trace indexer
420 */
421 protected void setIndexer(final ITmfTraceIndexer<ITmfTrace<ITmfEvent>> indexer) {
422 fIndexer = indexer;
423 }
424
425 /**
426 * Set the trace parser. Must be done at initialization time.
427 *
428 * @param parser the new trace parser
429 */
430 protected void setParser(final ITmfEventParser<T> parser) {
431 fParser = parser;
432 }
433
434 // ------------------------------------------------------------------------
435 // ITmfTrace - SeekEvent operations (returning a trace context)
436 // ------------------------------------------------------------------------
437
438 /* (non-Javadoc)
439 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(long)
440 */
441 @Override
442 public synchronized ITmfContext seekEvent(final long rank) {
443
444 // A rank <= 0 indicates to seek the first event
445 if (rank <= 0) {
446 ITmfContext context = seekEvent((ITmfLocation<?>) null);
447 context.setRank(0);
448 return context;
449 }
450
451 // Position the trace at the checkpoint
452 final ITmfContext context = fIndexer.seekIndex(rank);
453
454 // And locate the requested event context
455 long pos = context.getRank();
456 if (pos < rank) {
457 ITmfEvent event = getNext(context);
458 while ((event != null) && (++pos < rank)) {
459 event = getNext(context);
460 }
461 }
462 return context;
463 }
464
465 /* (non-Javadoc)
466 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
467 */
468 @Override
469 public synchronized ITmfContext seekEvent(final ITmfTimestamp timestamp) {
470
471 // A null timestamp indicates to seek the first event
472 if (timestamp == null) {
473 ITmfContext context = seekEvent((ITmfLocation<?>) null);
474 context.setRank(0);
475 return context;
476 }
477
478 // Position the trace at the checkpoint
479 ITmfContext context = fIndexer.seekIndex(timestamp);
480
481 // And locate the requested event context
482 final ITmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
483 ITmfEvent event = getNext(nextEventContext);
484 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
485 context = nextEventContext.clone();
486 event = getNext(nextEventContext);
487 }
488 if (event == null) {
489 context.setLocation(null);
490 context.setRank(ITmfContext.UNKNOWN_RANK);
491 }
492 return context;
493 }
494
495 // ------------------------------------------------------------------------
496 // ITmfTrace - Read operations (returning an actual event)
497 // ------------------------------------------------------------------------
498
499 /* (non-Javadoc)
500 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#readNextEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
501 */
502 @Override
503 public synchronized T getNext(final ITmfContext context) {
504 // parseEvent() does not update the context
505 final T event = fParser.parseEvent(context);
506 if (event != null) {
507 updateAttributes(context, event.getTimestamp());
508 context.setLocation(getCurrentLocation());
509 context.increaseRank();
510 processEvent(event);
511 }
512 return event;
513 }
514
515 /**
516 * Hook for special event processing by the concrete class
517 * (called by TmfTrace.getEvent())
518 *
519 * @param event the event
520 */
521 protected void processEvent(final ITmfEvent event) {
522 // Do nothing
523 }
524
525 /**
526 * Update the trace attributes
527 *
528 * @param context the current trace context
529 * @param timestamp the corresponding timestamp
530 */
531 protected synchronized void updateAttributes(final ITmfContext context, final ITmfTimestamp timestamp) {
532 if (fStartTime.equals(TmfTimestamp.BIG_BANG) || (fStartTime.compareTo(timestamp, false) > 0)) {
533 fStartTime = timestamp.clone();
534 }
535 if (fEndTime.equals(TmfTimestamp.BIG_CRUNCH) || (fEndTime.compareTo(timestamp, false) < 0)) {
536 fEndTime = timestamp.clone();
537 }
538 if (context.hasValidRank()) {
539 long rank = context.getRank();
540 if (fNbEvents <= rank) {
541 fNbEvents = rank + 1;
542 }
543 fIndexer.updateIndex(context, timestamp);
544 }
545 }
546
547 // ------------------------------------------------------------------------
548 // TmfDataProvider
549 // ------------------------------------------------------------------------
550
551 /* (non-Javadoc)
552 * @see org.eclipse.linuxtools.tmf.core.component.TmfDataProvider#armRequest(org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest)
553 */
554 @Override
555 protected ITmfContext armRequest(final ITmfDataRequest<T> request) {
556 if ((request instanceof ITmfEventRequest<?>)
557 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest<T>) request).getRange().getStartTime())
558 && (request.getIndex() == 0))
559 {
560 final ITmfContext context = seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
561 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
562 return context;
563
564 }
565 return seekEvent(request.getIndex());
566 }
567
568 // ------------------------------------------------------------------------
569 // toString
570 // ------------------------------------------------------------------------
571
572 /* (non-Javadoc)
573 * @see java.lang.Object#toString()
574 */
575 @Override
576 @SuppressWarnings("nls")
577 public synchronized String toString() {
578 return "TmfTrace [fPath=" + fPath + ", fCacheSize=" + fCacheSize
579 + ", fNbEvents=" + fNbEvents + ", fStartTime=" + fStartTime
580 + ", fEndTime=" + fEndTime + ", fStreamingInterval=" + fStreamingInterval + "]";
581 }
582
583 }
This page took 0.043909 seconds and 6 git commands to generate.