Refactor ITmfContext and fix dependencies
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTrace.java
CommitLineData
8c8bf09f 1/*******************************************************************************
e31e01e8 2 * Copyright (c) 2009, 2010 Ericsson
8c8bf09f
ASL
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
3791b5df 11 * Francois Chouinard - Updated as per TMF Trace Model 1.0
8c8bf09f
ASL
12 *******************************************************************************/
13
6c13869b 14package org.eclipse.linuxtools.tmf.core.trace;
8c8bf09f 15
6f4a1d2b 16import java.io.File;
62d1696a 17import java.io.FileNotFoundException;
62d1696a 18import java.util.Collections;
8c8bf09f
ASL
19import java.util.Vector;
20
12c155f5 21import org.eclipse.core.resources.IProject;
828e5592 22import org.eclipse.core.resources.IResource;
05bd3318
FC
23import org.eclipse.core.runtime.IProgressMonitor;
24import org.eclipse.core.runtime.IStatus;
c7e2f194 25import org.eclipse.core.runtime.Path;
05bd3318
FC
26import org.eclipse.core.runtime.Status;
27import org.eclipse.core.runtime.jobs.Job;
6c13869b 28import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider;
72f1e62a 29import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
4df4581d 30import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
6c13869b
FC
31import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
32import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
33import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
34import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
35import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
36import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
37import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
8c8bf09f
ASL
38
39/**
146a887c 40 * <b><u>TmfTrace</u></b>
8c8bf09f 41 * <p>
3791b5df
FC
42 * Abstract implementation of ITmfTrace. It should be sufficient to extend this
43 * class and provide implementation for <code>getCurrentLocation()</code> and
44 * <code>seekLocation()</code>, as well as a proper parser, to have a working
4e3aa37d 45 * concrete implementation.
8c8bf09f 46 */
3791b5df 47public abstract class TmfTrace<T extends ITmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T> {
62d1696a 48
e31e01e8 49 // ------------------------------------------------------------------------
62d1696a 50 // Constants
e31e01e8 51 // ------------------------------------------------------------------------
62d1696a 52
3791b5df
FC
53 /**
54 * The default number of events in an index page. Can be used as block size.
55 */
56 public static final int DEFAULT_INDEX_PAGE_SIZE = 1000;
8c8bf09f 57
e31e01e8 58 // ------------------------------------------------------------------------
8c8bf09f 59 // Attributes
e31e01e8 60 // ------------------------------------------------------------------------
8c8bf09f 61
b0a282fb 62 // The trace path
12c155f5 63 private String fPath;
b0a282fb 64
3791b5df
FC
65 /**
66 * The cache page size AND checkpoints interval
67 */
12c155f5 68 protected int fIndexPageSize = DEFAULT_INDEX_PAGE_SIZE;
62d1696a 69
3791b5df 70 // The set of event stream checkpoints
9f584e4c 71 protected Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
62d1696a
FC
72
73 // The number of events collected
a3fe52fc 74 protected long fNbEvents = 0;
62d1696a
FC
75
76 // The time span of the event stream
a4115405
FC
77 private ITmfTimestamp fStartTime = TmfTimestamp.BIG_CRUNCH;
78 private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG;
62d1696a 79
3791b5df
FC
80 /**
81 * The trace streaming interval (0 = no streaming)
82 */
83 protected long fStreamingInterval = 0;
84
85 // The resource used for persistent properties for this trace
828e5592
PT
86 private IResource fResource;
87
e31e01e8 88 // ------------------------------------------------------------------------
3791b5df 89 // Construction
e31e01e8 90 // ------------------------------------------------------------------------
8c8bf09f 91
62d1696a 92 /**
3791b5df 93 * The default, parameterless, constructor
62d1696a 94 */
3791b5df
FC
95 public TmfTrace() {
96 super();
05bd3318
FC
97 }
98
99 /**
3791b5df
FC
100 * The standard constructor (non-streaming trace)
101 *
102 * @param name the trace display name
103 * @param type the trace event type
104 * @param path the trace path
105 * @param pageSize the trace index page size
106 * @param indexTrace whether to start indexing the trace or not
05bd3318
FC
107 * @throws FileNotFoundException
108 */
3791b5df
FC
109 protected TmfTrace(String name, Class<T> type, String path, int indexPageSize, boolean indexTrace) throws FileNotFoundException {
110 this(name, type, path, 0, indexPageSize, indexTrace);
05bd3318
FC
111 }
112
113 /**
3791b5df
FC
114 * The full constructor
115 *
116 * @param name the trace display name
117 * @param type the trace event type
118 * @param path the trace path
119 * @param pageSize the trace index page size
120 * @param indexTrace whether to start indexing the trace or not
05bd3318
FC
121 * @throws FileNotFoundException
122 */
3791b5df 123 protected TmfTrace(String name, Class<T> type, String path, long interval, int indexPageSize, boolean indexTrace) throws FileNotFoundException {
00641a97 124 super();
3118edf1 125 initTrace(name, path, type);
3791b5df 126 fStreamingInterval = interval;
3118edf1
FC
127 fIndexPageSize = (indexPageSize >0) ? indexPageSize : DEFAULT_INDEX_PAGE_SIZE;
128 if (indexTrace)
129 indexTrace(false);
8c8bf09f
ASL
130 }
131
3791b5df
FC
132 /**
133 * Copy constructor
134 *
135 * @param trace the original trace
136 */
ff4ed569 137 @SuppressWarnings("unchecked")
3791b5df
FC
138 public TmfTrace(ITmfTrace<T> trace) throws FileNotFoundException {
139 super();
140 if (trace == null)
141 throw new IllegalArgumentException();
142 initTrace(getName(), getPath(), (Class<T>) getType());
143 fStreamingInterval = getStreamingInterval();
144 fIndexPageSize = getIndexPageSize();
145 indexTrace(false);
146 }
147
148 // ------------------------------------------------------------------------
149 // Cloneable
150 // ------------------------------------------------------------------------
151
152 /* (non-Javadoc)
153 * @see java.lang.Object#clone()
154 */
12c155f5 155 @Override
3791b5df
FC
156 @SuppressWarnings("unchecked")
157 public TmfTrace<T> clone() {
158 TmfTrace<T> clone = null;
159 try {
160 clone = (TmfTrace<T>) super.clone();
161// clone.fTrace = fTrace;
162// clone.fRank = fRank;
163// clone.fTimestamp = fTimestamp != null ? fTimestamp.clone() : null;
164// clone.fSource = fSource;
165// clone.fType = fType != null ? fType.clone() : null;
166// clone.fContent = fContent != null ? fContent.clone() : null;
167// clone.fReference = fReference;
168 } catch (CloneNotSupportedException e) {
169 }
12c155f5 170 return clone;
8c8bf09f
ASL
171 }
172
e31e01e8 173 // ------------------------------------------------------------------------
3791b5df
FC
174 // ITmfTrace - initializers
175 // ------------------------------------------------------------------------
176
177 /* (non-Javadoc)
178 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#initTrace(java.lang.String, java.lang.String, java.lang.Class)
179 */
180 @Override
181 public void initTrace(String name, String path, Class<T> type) throws FileNotFoundException {
182 fPath = path;
183 String traceName = name;
184 // If no display name was provided, extract it from the trace path
185 if (traceName == null) {
186 if (path != null) {
187 int sep = path.lastIndexOf(Path.SEPARATOR);
188 traceName = (sep >= 0) ? path.substring(sep + 1) : path;
189 } else {
190 traceName = ""; //$NON-NLS-1$
191 }
192 }
193 super.init(traceName, type);
194 }
195
196 /* (non-Javadoc)
197 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)
198 */
199 @Override
200 public boolean validate(IProject project, String path) {
201 File file = new File(path);
202 return file.exists();
203 }
204
205 /*
206 * (non-Javadoc)
207 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#setResource(org.eclipse.core.resources.IResource)
208 */
209 @Override
210 public void setResource(IResource resource) {
211 fResource = resource;
212 }
213
214 // ------------------------------------------------------------------------
215 // ITmfTrace - accessors
e31e01e8 216 // ------------------------------------------------------------------------
8c8bf09f 217
62d1696a 218 /**
b0a282fb 219 * @return the trace path
62d1696a 220 */
d4011df2 221 @Override
12c155f5 222 public String getPath() {
b0a282fb 223 return fPath;
8c8bf09f
ASL
224 }
225
3791b5df
FC
226 /*
227 * (non-Javadoc)
228 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
62d1696a 229 */
d4011df2 230 @Override
3791b5df
FC
231 public IResource getResource() {
232 return fResource;
8c8bf09f
ASL
233 }
234
3791b5df
FC
235 /* (non-Javadoc)
236 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
b0a282fb 237 */
d4011df2 238 @Override
3791b5df
FC
239 public synchronized long getNbEvents() {
240 return fNbEvents;
b0a282fb
FC
241 }
242
62d1696a
FC
243 /* (non-Javadoc)
244 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
245 */
d4011df2 246 @Override
12c155f5 247 public TmfTimeRange getTimeRange() {
cb866e08 248 return new TmfTimeRange(fStartTime, fEndTime);
8c8bf09f
ASL
249 }
250
e31e01e8
FC
251 /* (non-Javadoc)
252 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
253 */
d4011df2 254 @Override
4df4581d 255 public ITmfTimestamp getStartTime() {
3791b5df 256 return fStartTime.clone();
146a887c
FC
257 }
258
e31e01e8
FC
259 /* (non-Javadoc)
260 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
261 */
d4011df2 262 @Override
4df4581d 263 public ITmfTimestamp getEndTime() {
3791b5df 264 return fEndTime.clone();
146a887c
FC
265 }
266
1b70b6dc
PT
267 /* (non-Javadoc)
268 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
269 */
270 @Override
271 public long getStreamingInterval() {
3791b5df 272 return fStreamingInterval;
1b70b6dc
PT
273 }
274
3791b5df
FC
275 /* (non-Javadoc)
276 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getIndexPageSize()
abfad0aa 277 */
d4011df2 278 @Override
3791b5df
FC
279 public int getIndexPageSize() {
280 return fIndexPageSize;
abfad0aa
FC
281 }
282
e31e01e8 283 // ------------------------------------------------------------------------
3791b5df 284 // ITmfTrace - indexing
e31e01e8 285 // ------------------------------------------------------------------------
8c8bf09f 286
3791b5df
FC
287 /*
288 * The index is a list of contexts that point to events at regular interval
289 * (rank-wise) in the trace. After it is built, the index can be used to
290 * quickly access any event by rank or timestamp.
291 *
292 * fIndexPageSize holds the event interval (default INDEX_PAGE_SIZE).
293 */
4e3aa37d 294
3791b5df
FC
295 @Override
296 @SuppressWarnings({ "unchecked" })
297 public void indexTrace(boolean waitForCompletion) {
4e3aa37d 298
3791b5df
FC
299 // The monitoring job
300 final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
301 @Override
302 protected IStatus run(IProgressMonitor monitor) {
303 while (!monitor.isCanceled()) {
304 try {
305 Thread.sleep(100);
306 } catch (InterruptedException e) {
307 return Status.OK_STATUS;
308 }
309 }
310 monitor.done();
311 return Status.OK_STATUS;
312 }
313 };
314 job.schedule();
12c155f5 315
3791b5df
FC
316 // Clear the checkpoints
317 fCheckpoints.clear();
12c155f5 318
3791b5df
FC
319 // Build a background request for all the trace data. The index is
320 // updated as we go by getNextEvent().
321 ITmfEventRequest<ITmfEvent> request = new TmfEventRequest<ITmfEvent>(ITmfEvent.class, TmfTimeRange.ETERNITY,
322 TmfDataRequest.ALL_DATA, fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND)
323 {
324 ITmfTimestamp startTime = null;
325 ITmfTimestamp lastTime = null;
12c155f5 326
3791b5df
FC
327 @Override
328 public void handleData(ITmfEvent event) {
329 super.handleData(event);
330 if (event != null) {
331 ITmfTimestamp timestamp = event.getTimestamp();
332 if (startTime == null)
333 startTime = timestamp.clone();
334 lastTime = timestamp.clone();
335
336 // Update the trace status at regular intervals
337 if ((getNbRead() % fIndexPageSize) == 0) {
338 updateTraceStatus();
339 }
340 }
341 }
342
343 @Override
344 public void handleSuccess() {
345 updateTraceStatus();
346 }
347
348 @Override
349 public void handleCompleted() {
350 job.cancel();
351 super.handleCompleted();
352 }
353
354 private synchronized void updateTraceStatus() {
355 int nbRead = getNbRead();
356 if (nbRead != 0) {
357 fStartTime = startTime;
358 fEndTime = lastTime;
359 fNbEvents = nbRead;
360 notifyListeners();
361 }
362 }
363 };
364
365 // Submit the request and wait for completion if required
366 sendRequest((ITmfDataRequest<T>) request);
367 if (waitForCompletion)
368 try {
369 request.waitForCompletion();
370 } catch (InterruptedException e) {
371 }
12c155f5
FC
372 }
373
3791b5df
FC
374 private void notifyListeners() {
375 broadcast(new TmfTraceUpdatedSignal(this, this, new TmfTimeRange(fStartTime, fEndTime)));
12c155f5
FC
376 }
377
378 // ------------------------------------------------------------------------
3791b5df 379 // ITmfTrace - seek operations
12c155f5 380 // ------------------------------------------------------------------------
e31e01e8 381
146a887c 382 /* (non-Javadoc)
3791b5df 383 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
146a887c 384 */
d4011df2 385 @Override
3791b5df 386 public ITmfContext seekEvent(ITmfTimestamp ts) {
62d1696a 387
beae214a 388 ITmfTimestamp timestamp = ts;
12c155f5 389 if (timestamp == null) {
a4115405 390 timestamp = TmfTimestamp.BIG_BANG;
12c155f5 391 }
4e3aa37d 392
12c155f5
FC
393 // First, find the right checkpoint
394 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
62d1696a 395
8d2e2848 396 // In the very likely case that the checkpoint was not found, bsearch
62d1696a
FC
397 // returns its negated would-be location (not an offset...). From that
398 // index, we can then position the stream and get the event.
399 if (index < 0) {
400 index = Math.max(0, -(index + 2));
401 }
402
403 // Position the stream at the checkpoint
452ad365 404 ITmfLocation<?> location;
e31e01e8 405 synchronized (fCheckpoints) {
beae214a 406 if (!fCheckpoints.isEmpty()) {
12c155f5
FC
407 if (index >= fCheckpoints.size()) {
408 index = fCheckpoints.size() - 1;
409 }
410 location = fCheckpoints.elementAt(index).getLocation();
411 } else {
412 location = null;
413 }
8d2e2848 414 }
3791b5df 415 ITmfContext context = seekLocation(location);
54d55ced 416 context.setRank(index * fIndexPageSize);
62d1696a 417
54d55ced 418 // And locate the event
3791b5df 419 ITmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
72f1e62a 420 ITmfEvent event = getNextEvent(nextEventContext);
62d1696a 421 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
12c155f5 422 context.setLocation(nextEventContext.getLocation().clone());
cbdacf03 423 context.increaseRank();
12c155f5 424 event = getNextEvent(nextEventContext);
62d1696a
FC
425 }
426
54d55ced 427 return context;
62d1696a
FC
428 }
429
146a887c 430 /* (non-Javadoc)
3791b5df 431 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(long)
146a887c 432 */
d4011df2 433 @Override
3791b5df 434 public ITmfContext seekEvent(long rank) {
62d1696a
FC
435
436 // Position the stream at the previous checkpoint
9f584e4c 437 int index = (int) rank / fIndexPageSize;
452ad365 438 ITmfLocation<?> location;
e31e01e8 439 synchronized (fCheckpoints) {
beae214a 440 if (fCheckpoints.isEmpty()) {
12c155f5
FC
441 location = null;
442 } else {
443 if (index >= fCheckpoints.size()) {
444 index = fCheckpoints.size() - 1;
445 }
446 location = fCheckpoints.elementAt(index).getLocation();
447 }
8d2e2848 448 }
54d55ced 449
3791b5df 450 ITmfContext context = seekLocation(location);
9f584e4c
FC
451 long pos = index * fIndexPageSize;
452 context.setRank(pos);
e31e01e8 453
9f584e4c 454 if (pos < rank) {
72f1e62a 455 ITmfEvent event = getNextEvent(context);
9f584e4c 456 while (event != null && ++pos < rank) {
12c155f5 457 event = getNextEvent(context);
e31e01e8 458 }
165c977c 459 }
62d1696a 460
8f50c396 461 return context;
8c8bf09f
ASL
462 }
463
3791b5df
FC
464 // ------------------------------------------------------------------------
465 // Operations
466 // ------------------------------------------------------------------------
467
468 // ------------------------------------------------------------------------
469 // Operations
470 // ------------------------------------------------------------------------
471
472 @SuppressWarnings("unchecked")
473 public Vector<TmfCheckpoint> getCheckpoints() {
474 return (Vector<TmfCheckpoint>) fCheckpoints.clone();
475 }
476
477 /**
478 * Returns the rank of the first event with the requested timestamp. If none, returns the index of the next event
479 * (if any).
480 *
481 * @param timestamp the requested event timestamp
482 * @return the corresponding event rank
483 */
484 @Override
485 public long getRank(ITmfTimestamp timestamp) {
486 ITmfContext context = seekEvent(timestamp);
487 return context.getRank();
488 }
489
490 // ------------------------------------------------------------------------
491 // Operators
492 // ------------------------------------------------------------------------
493
494 protected void setTimeRange(TmfTimeRange range) {
495 fStartTime = range.getStartTime();
496 fEndTime = range.getEndTime();
497 }
498
499 protected void setStartTime(ITmfTimestamp startTime) {
500 fStartTime = startTime;
501 }
502
503 protected void setEndTime(ITmfTimestamp endTime) {
504 fEndTime = endTime;
505 }
506
507 // ------------------------------------------------------------------------
508 // TmfProvider
509 // ------------------------------------------------------------------------
510
511 @Override
512 public ITmfContext armRequest(ITmfDataRequest<T> request) {
513 if (request instanceof ITmfEventRequest<?>
514 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest<T>) request).getRange().getStartTime()) && request.getIndex() == 0) {
515 ITmfContext context = seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
516 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
517 return context;
518
519 }
520 return seekEvent(request.getIndex());
521 }
522
523 /**
524 * Return the next piece of data based on the context supplied. The context would typically be updated for the
525 * subsequent read.
526 *
527 * @param context
528 * @return the event referred to by context
529 */
530 @SuppressWarnings("unchecked")
531 @Override
532 public T getNext(ITmfContext context) {
533 if (context instanceof TmfContext) {
534 return (T) getNextEvent((TmfContext) context);
535 }
536 return null;
537 }
538
539 // ------------------------------------------------------------------------
540 // ITmfTrace
541 // ------------------------------------------------------------------------
542
543
12c155f5
FC
544 /*
545 * (non-Javadoc)
546 *
547 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse.
548 * linuxtools.tmf.trace.ITmfTrace.TraceContext)
549 */
550 @Override
a1440d1f 551 public synchronized ITmfEvent getNextEvent(ITmfContext context) {
12c155f5 552 // parseEvent() does not update the context
72f1e62a 553 ITmfEvent event = parseEvent(context);
12c155f5
FC
554 if (event != null) {
555 updateIndex(context, context.getRank(), event.getTimestamp());
556 context.setLocation(getCurrentLocation());
cbdacf03 557 context.increaseRank();
12c155f5
FC
558 processEvent(event);
559 }
560 return event;
561 }
550d787e 562
4df4581d 563 protected synchronized void updateIndex(ITmfContext context, long rank, ITmfTimestamp timestamp) {
12c155f5
FC
564 if (fStartTime.compareTo(timestamp, false) > 0)
565 fStartTime = timestamp;
566 if (fEndTime.compareTo(timestamp, false) < 0)
567 fEndTime = timestamp;
cbdacf03 568 if (context.hasValidRank()) {
12c155f5
FC
569 if (fNbEvents <= rank)
570 fNbEvents = rank + 1;
571 // Build the index as we go along
572 if ((rank % fIndexPageSize) == 0) {
573 // Determine the table position
574 long position = rank / fIndexPageSize;
575 // Add new entry at proper location (if empty)
576 if (fCheckpoints.size() == position) {
577 ITmfLocation<?> location = context.getLocation().clone();
578 fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location));
579 // System.out.println(getName() + "[" + (fCheckpoints.size()
580 // - 1) + "] " + timestamp + ", " + location.toString());
581 }
582 }
583 }
584 }
4e3aa37d 585
e31e01e8 586 /**
12c155f5
FC
587 * Hook for special processing by the concrete class (called by getNextEvent())
588 *
589 * @param event
590 */
72f1e62a 591 protected void processEvent(ITmfEvent event) {
12c155f5
FC
592 // Do nothing by default
593 }
594
595 // ------------------------------------------------------------------------
596 // toString
597 // ------------------------------------------------------------------------
598
599 /* (non-Javadoc)
600 * @see java.lang.Object#toString()
4e3aa37d 601 */
d4011df2 602 @Override
12c155f5
FC
603 @SuppressWarnings("nls")
604 public String toString() {
605 return "[TmfTrace (" + getName() + ")]";
606 }
607
8c8bf09f 608}
This page took 0.071391 seconds and 5 git commands to generate.