Refactor ITmfContext and fix dependencies
[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
43 * class and provide implementation for <code>getCurrentLocation()</code> and
44 * <code>seekLocation()</code>, as well as a proper parser, to have a working
45 * concrete implementation.
46 */
47 public abstract class TmfTrace<T extends ITmfEvent> extends TmfEventProvider<T> implements ITmfTrace<T> {
48
49 // ------------------------------------------------------------------------
50 // Constants
51 // ------------------------------------------------------------------------
52
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;
57
58 // ------------------------------------------------------------------------
59 // Attributes
60 // ------------------------------------------------------------------------
61
62 // The trace path
63 private String fPath;
64
65 /**
66 * The cache page size AND checkpoints interval
67 */
68 protected int fIndexPageSize = DEFAULT_INDEX_PAGE_SIZE;
69
70 // The set of event stream checkpoints
71 protected Vector<TmfCheckpoint> fCheckpoints = new Vector<TmfCheckpoint>();
72
73 // The number of events collected
74 protected long fNbEvents = 0;
75
76 // The time span of the event stream
77 private ITmfTimestamp fStartTime = TmfTimestamp.BIG_CRUNCH;
78 private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG;
79
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
86 private IResource fResource;
87
88 // ------------------------------------------------------------------------
89 // Construction
90 // ------------------------------------------------------------------------
91
92 /**
93 * The default, parameterless, constructor
94 */
95 public TmfTrace() {
96 super();
97 }
98
99 /**
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
107 * @throws FileNotFoundException
108 */
109 protected TmfTrace(String name, Class<T> type, String path, int indexPageSize, boolean indexTrace) throws FileNotFoundException {
110 this(name, 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(String name, Class<T> type, String path, long interval, int indexPageSize, boolean indexTrace) throws FileNotFoundException {
124 super();
125 initTrace(name, path, type);
126 fStreamingInterval = interval;
127 fIndexPageSize = (indexPageSize >0) ? indexPageSize : DEFAULT_INDEX_PAGE_SIZE;
128 if (indexTrace)
129 indexTrace(false);
130 }
131
132 /**
133 * Copy constructor
134 *
135 * @param trace the original trace
136 */
137 @SuppressWarnings("unchecked")
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 */
155 @Override
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 }
170 return clone;
171 }
172
173 // ------------------------------------------------------------------------
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
216 // ------------------------------------------------------------------------
217
218 /**
219 * @return the trace path
220 */
221 @Override
222 public String getPath() {
223 return fPath;
224 }
225
226 /*
227 * (non-Javadoc)
228 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
229 */
230 @Override
231 public IResource getResource() {
232 return fResource;
233 }
234
235 /* (non-Javadoc)
236 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents()
237 */
238 @Override
239 public synchronized long getNbEvents() {
240 return fNbEvents;
241 }
242
243 /* (non-Javadoc)
244 * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange()
245 */
246 @Override
247 public TmfTimeRange getTimeRange() {
248 return new TmfTimeRange(fStartTime, fEndTime);
249 }
250
251 /* (non-Javadoc)
252 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime()
253 */
254 @Override
255 public ITmfTimestamp getStartTime() {
256 return fStartTime.clone();
257 }
258
259 /* (non-Javadoc)
260 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime()
261 */
262 @Override
263 public ITmfTimestamp getEndTime() {
264 return fEndTime.clone();
265 }
266
267 /* (non-Javadoc)
268 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
269 */
270 @Override
271 public long getStreamingInterval() {
272 return fStreamingInterval;
273 }
274
275 /* (non-Javadoc)
276 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getIndexPageSize()
277 */
278 @Override
279 public int getIndexPageSize() {
280 return fIndexPageSize;
281 }
282
283 // ------------------------------------------------------------------------
284 // ITmfTrace - indexing
285 // ------------------------------------------------------------------------
286
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 */
294
295 @Override
296 @SuppressWarnings({ "unchecked" })
297 public void indexTrace(boolean waitForCompletion) {
298
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();
315
316 // Clear the checkpoints
317 fCheckpoints.clear();
318
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;
326
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 }
372 }
373
374 private void notifyListeners() {
375 broadcast(new TmfTraceUpdatedSignal(this, this, new TmfTimeRange(fStartTime, fEndTime)));
376 }
377
378 // ------------------------------------------------------------------------
379 // ITmfTrace - seek operations
380 // ------------------------------------------------------------------------
381
382 /* (non-Javadoc)
383 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
384 */
385 @Override
386 public ITmfContext seekEvent(ITmfTimestamp ts) {
387
388 ITmfTimestamp timestamp = ts;
389 if (timestamp == null) {
390 timestamp = TmfTimestamp.BIG_BANG;
391 }
392
393 // First, find the right checkpoint
394 int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null));
395
396 // In the very likely case that the checkpoint was not found, bsearch
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
404 ITmfLocation<?> location;
405 synchronized (fCheckpoints) {
406 if (!fCheckpoints.isEmpty()) {
407 if (index >= fCheckpoints.size()) {
408 index = fCheckpoints.size() - 1;
409 }
410 location = fCheckpoints.elementAt(index).getLocation();
411 } else {
412 location = null;
413 }
414 }
415 ITmfContext context = seekLocation(location);
416 context.setRank(index * fIndexPageSize);
417
418 // And locate the event
419 ITmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype...
420 ITmfEvent event = getNextEvent(nextEventContext);
421 while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) {
422 context.setLocation(nextEventContext.getLocation().clone());
423 context.increaseRank();
424 event = getNextEvent(nextEventContext);
425 }
426
427 return context;
428 }
429
430 /* (non-Javadoc)
431 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(long)
432 */
433 @Override
434 public ITmfContext seekEvent(long rank) {
435
436 // Position the stream at the previous checkpoint
437 int index = (int) rank / fIndexPageSize;
438 ITmfLocation<?> location;
439 synchronized (fCheckpoints) {
440 if (fCheckpoints.isEmpty()) {
441 location = null;
442 } else {
443 if (index >= fCheckpoints.size()) {
444 index = fCheckpoints.size() - 1;
445 }
446 location = fCheckpoints.elementAt(index).getLocation();
447 }
448 }
449
450 ITmfContext context = seekLocation(location);
451 long pos = index * fIndexPageSize;
452 context.setRank(pos);
453
454 if (pos < rank) {
455 ITmfEvent event = getNextEvent(context);
456 while (event != null && ++pos < rank) {
457 event = getNextEvent(context);
458 }
459 }
460
461 return context;
462 }
463
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
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
551 public synchronized ITmfEvent getNextEvent(ITmfContext context) {
552 // parseEvent() does not update the context
553 ITmfEvent event = parseEvent(context);
554 if (event != null) {
555 updateIndex(context, context.getRank(), event.getTimestamp());
556 context.setLocation(getCurrentLocation());
557 context.increaseRank();
558 processEvent(event);
559 }
560 return event;
561 }
562
563 protected synchronized void updateIndex(ITmfContext context, long rank, ITmfTimestamp timestamp) {
564 if (fStartTime.compareTo(timestamp, false) > 0)
565 fStartTime = timestamp;
566 if (fEndTime.compareTo(timestamp, false) < 0)
567 fEndTime = timestamp;
568 if (context.hasValidRank()) {
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 }
585
586 /**
587 * Hook for special processing by the concrete class (called by getNextEvent())
588 *
589 * @param event
590 */
591 protected void processEvent(ITmfEvent event) {
592 // Do nothing by default
593 }
594
595 // ------------------------------------------------------------------------
596 // toString
597 // ------------------------------------------------------------------------
598
599 /* (non-Javadoc)
600 * @see java.lang.Object#toString()
601 */
602 @Override
603 @SuppressWarnings("nls")
604 public String toString() {
605 return "[TmfTrace (" + getName() + ")]";
606 }
607
608 }
This page took 0.065281 seconds and 6 git commands to generate.