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