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