Update some javadocs
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfExperiment.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 org.eclipse.core.resources.IFile;
17 import org.eclipse.core.resources.IProject;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.linuxtools.internal.tmf.core.trace.TmfExperimentContext;
20 import org.eclipse.linuxtools.internal.tmf.core.trace.TmfExperimentLocation;
21 import org.eclipse.linuxtools.internal.tmf.core.trace.TmfLocationArray;
22 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
23 import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
24 import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
25 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
26 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
27 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
28 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
29 import org.eclipse.linuxtools.tmf.core.signal.TmfEndSynchSignal;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal;
31 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
32 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
33 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
34 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
35 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
36
37 /**
38 * TmfExperiment presents a time-ordered, unified view of a set of ITmfTrace:s
39 * that are part of a tracing experiment.
40 *
41 * @version 1.0
42 * @author Francois Chouinard
43 */
44 public class TmfExperiment<T extends ITmfEvent> extends TmfTrace<T> implements ITmfEventParser<T> {
45
46 // ------------------------------------------------------------------------
47 // Constants
48 // ------------------------------------------------------------------------
49
50 /**
51 * The default index page size
52 */
53 public static final int DEFAULT_INDEX_PAGE_SIZE = 5000;
54
55 // ------------------------------------------------------------------------
56 // Attributes
57 // ------------------------------------------------------------------------
58
59 /**
60 * The currently selected experiment (null if none)
61 */
62 protected static TmfExperiment<?> fCurrentExperiment = null;
63
64 /**
65 * The set of traces that constitute the experiment
66 */
67 protected ITmfTrace<T>[] fTraces;
68
69 /**
70 * The set of traces that constitute the experiment
71 */
72 private boolean fInitialized = false;
73
74 /**
75 * The experiment bookmarks file
76 */
77 private IFile fBookmarksFile;
78
79
80 // Saved experiment context (optimization)
81 private TmfExperimentContext fExperimentContext;
82
83 // ------------------------------------------------------------------------
84 // Construction
85 // ------------------------------------------------------------------------
86
87 /**
88 * @param type
89 * @param id
90 * @param traces
91 * @throws TmfTraceException
92 */
93 public TmfExperiment(final Class<T> type, final String id, final ITmfTrace<T>[] traces) {
94 this(type, id, traces, DEFAULT_INDEX_PAGE_SIZE);
95 }
96
97 /**
98 * @param type
99 * @param id
100 * @param traces
101 * @param indexPageSize
102 * @throws TmfTraceException
103 */
104 @SuppressWarnings({ "unchecked", "rawtypes" })
105 public TmfExperiment(final Class<T> type, final String path, final ITmfTrace<T>[] traces, final int indexPageSize) {
106 setCacheSize(indexPageSize);
107 setStreamingInterval(0);
108 setIndexer(new TmfCheckpointIndexer(this, indexPageSize));
109 setParser(this);
110 try {
111 super.initialize(null, path, type);
112 } catch (TmfTraceException e) {
113 e.printStackTrace();
114 }
115
116 fTraces = traces;
117 setTimeRange(TmfTimeRange.NULL_RANGE);
118 }
119
120 /**
121 * Clears the experiment
122 */
123 @Override
124 @SuppressWarnings("rawtypes")
125 public synchronized void dispose() {
126
127 final TmfExperimentDisposedSignal<T> signal = new TmfExperimentDisposedSignal<T>(this, this);
128 broadcast(signal);
129
130 if (fCurrentExperiment == this) {
131 fCurrentExperiment = null;
132 }
133
134 if (fTraces != null) {
135 for (final ITmfTrace trace : fTraces)
136 trace.dispose();
137 fTraces = null;
138 }
139 super.dispose();
140 }
141
142 // ------------------------------------------------------------------------
143 // ITmfTrace - Initializers
144 // ------------------------------------------------------------------------
145
146 /* (non-Javadoc)
147 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#validate(org.eclipse.core.resources.IProject, java.lang.String)
148 */
149 @Override
150 public boolean validate(final IProject project, final String path) {
151 return true;
152 }
153
154 /* (non-Javadoc)
155 * @see org.eclipse.linuxtools.tmf.core.trace.TmfTrace#initTrace(org.eclipse.core.resources.IResource, java.lang.String, java.lang.Class)
156 */
157 @Override
158 public void initTrace(final IResource resource, final String path, final Class<T> type) {
159 }
160
161 // ------------------------------------------------------------------------
162 // Accessors
163 // ------------------------------------------------------------------------
164
165 /**
166 * Selects the current, framework-wide, experiment
167 *
168 * @param experiment das experiment
169 */
170 public static void setCurrentExperiment(final TmfExperiment<?> experiment) {
171 if (fCurrentExperiment != null && fCurrentExperiment != experiment) {
172 fCurrentExperiment.dispose();
173 }
174 fCurrentExperiment = experiment;
175 }
176
177 /**
178 * @return das experiment
179 */
180 public static TmfExperiment<?> getCurrentExperiment() {
181 return fCurrentExperiment;
182 }
183
184 /**
185 * Get the list of traces. Handle with care...
186 *
187 * @return the experiment traces
188 */
189 public ITmfTrace<T>[] getTraces() {
190 return fTraces;
191 }
192
193 /**
194 * Returns the timestamp of the event at the requested index. If none,
195 * returns null.
196 *
197 * @param index the event index (rank)
198 * @return the corresponding event timestamp
199 */
200 public ITmfTimestamp getTimestamp(final int index) {
201 final ITmfContext context = seekEvent(index);
202 final ITmfEvent event = getNext(context);
203 return (event != null) ? event.getTimestamp() : null;
204 }
205
206 /**
207 * Set the file to be used for bookmarks on this experiment
208 *
209 * @param file the bookmarks file
210 */
211 public void setBookmarksFile(final IFile file) {
212 fBookmarksFile = file;
213 }
214
215 /**
216 * Get the file used for bookmarks on this experiment
217 *
218 * @return the bookmarks file or null if none is set
219 */
220 public IFile getBookmarksFile() {
221 return fBookmarksFile;
222 }
223
224 // ------------------------------------------------------------------------
225 // Request management
226 // ------------------------------------------------------------------------
227
228 @Override
229 protected ITmfContext armRequest(final ITmfDataRequest<T> request) {
230 if (request instanceof ITmfEventRequest<?>
231 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest<T>) request).getRange().getStartTime())
232 && request.getIndex() == 0)
233 {
234 final ITmfContext context = seekEvent(((ITmfEventRequest<T>) request).getRange().getStartTime());
235 ((ITmfEventRequest<T>) request).setStartIndex((int) context.getRank());
236 return context;
237
238 }
239
240 // Check if we are already at the right index
241 if ((fExperimentContext != null) && fExperimentContext.getRank() == request.getIndex()) {
242 return fExperimentContext;
243 }
244
245 return seekEvent(request.getIndex());
246 }
247
248 // ------------------------------------------------------------------------
249 // ITmfTrace trace positioning
250 // ------------------------------------------------------------------------
251
252 /* (non-Javadoc)
253 *
254 * Returns a brand new context based on the location provided and
255 * initializes the event queues
256 *
257 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfLocation)
258 */
259 @Override
260 public synchronized ITmfContext seekEvent(final ITmfLocation<?> location) {
261 // Validate the location
262 if (location != null && !(location instanceof TmfExperimentLocation)) {
263 return null; // Throw an exception?
264 }
265 // Make sure we have something to read from
266 if (fTraces == null) {
267 return null;
268 }
269
270 // Instantiate the location
271 final TmfExperimentLocation expLocation = (location == null)
272 ? new TmfExperimentLocation(new TmfLocationArray(new ITmfLocation<?>[fTraces.length]))
273 : (TmfExperimentLocation) location.clone();
274
275 // Create and populate the context's traces contexts
276 final TmfExperimentContext context = new TmfExperimentContext(new ITmfContext[fTraces.length]);
277
278 for (int i = 0; i < fTraces.length; i++) {
279 // Get the relevant trace attributes
280 final ITmfLocation<?> traceLocation = expLocation.getLocation().getLocations()[i];
281 context.getContexts()[i] = fTraces[i].seekEvent(traceLocation);
282 expLocation.getLocation().getLocations()[i] = context.getContexts()[i].getLocation().clone();
283 context.getEvents()[i] = fTraces[i].getNext(context.getContexts()[i]);
284 }
285
286 // Finalize context
287 context.setLocation(expLocation);
288 context.setLastTrace(TmfExperimentContext.NO_TRACE);
289 context.setRank(ITmfContext.UNKNOWN_RANK);
290
291 fExperimentContext = context;
292
293 return (ITmfContext) context;
294 }
295
296 /* (non-Javadoc)
297 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(double)
298 */
299 @Override
300 public ITmfContext seekEvent(final double ratio) {
301 final ITmfContext context = seekEvent((long) (ratio * getNbEvents()));
302 return context;
303 }
304
305 /* (non-Javadoc)
306 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getLocationRatio(org.eclipse.linuxtools.tmf.core.trace.ITmfLocation)
307 */
308 @Override
309 public double getLocationRatio(final ITmfLocation<?> location) {
310 if (location instanceof TmfExperimentLocation) {
311 return (double) seekEvent(location).getRank() / getNbEvents();
312 }
313 return 0.0;
314 }
315
316 /* (non-Javadoc)
317 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getCurrentLocation()
318 */
319 @Override
320 public ITmfLocation<?> getCurrentLocation() {
321 ITmfLocation<?>[] locations = new ITmfLocation<?>[fTraces.length];
322 for (int i = 0; i < fTraces.length; i++) {
323 locations[i] = fTraces[i].getCurrentLocation();
324 }
325 return new TmfExperimentLocation(new TmfLocationArray(locations));
326 }
327
328 // ------------------------------------------------------------------------
329 // ITmfTrace trace positioning
330 // ------------------------------------------------------------------------
331
332 /* (non-Javadoc)
333 * @see org.eclipse.linuxtools.tmf.core.trace.TmfTrace#getNext(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
334 */
335 @Override
336 public synchronized T getNext(final ITmfContext context) {
337 final ITmfContext previousContext = (TmfExperimentContext) context.clone();
338 final T event = parseEvent(context);
339 if (event != null) {
340 updateAttributes(previousContext, event.getTimestamp());
341
342 fExperimentContext = (TmfExperimentContext) context;
343 int trace = fExperimentContext.getLastTrace();
344 if (trace != TmfExperimentContext.NO_TRACE) {
345 TmfExperimentLocation location = (TmfExperimentLocation) fExperimentContext.getLocation();
346 location.getLocation().getLocations()[trace] = fExperimentContext.getContexts()[trace].getLocation();
347 }
348
349 context.increaseRank();
350 processEvent(event);
351 }
352 return event;
353 }
354
355 /* (non-Javadoc)
356 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser#parseEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
357 */
358 @SuppressWarnings("unchecked")
359 @Override
360 public T parseEvent(ITmfContext context) {
361
362 // Validate the context
363 if (!(context instanceof TmfExperimentContext)) {
364 return null; // Throw an exception?
365 }
366
367 TmfExperimentContext expContext = (TmfExperimentContext) context;
368
369 // If an event was consumed previously, first get the next one from that trace
370 final int lastTrace = expContext.getLastTrace();
371 if (lastTrace != TmfExperimentContext.NO_TRACE) {
372 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
373 expContext.getEvents()[lastTrace] = fTraces[lastTrace].getNext(traceContext);
374 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
375 }
376
377 // Scan the candidate events and identify the "next" trace to read from
378 int trace = TmfExperimentContext.NO_TRACE;
379 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
380 for (int i = 0; i < fTraces.length; i++) {
381 final ITmfEvent event = expContext.getEvents()[i];
382 if (event != null && event.getTimestamp() != null) {
383 final ITmfTimestamp otherTS = event.getTimestamp();
384 if (otherTS.compareTo(timestamp, true) < 0) {
385 trace = i;
386 timestamp = otherTS;
387 }
388 }
389 }
390
391 T event = null;
392 if (trace != TmfExperimentContext.NO_TRACE) {
393 event = (T) expContext.getEvents()[trace];
394 }
395
396 expContext.setLastTrace(trace);
397 return event;
398 }
399
400 /* (non-Javadoc)
401 * @see java.lang.Object#toString()
402 */
403 @Override
404 @SuppressWarnings("nls")
405 public String toString() {
406 return "[TmfExperiment (" + getName() + ")]";
407 }
408
409 // ------------------------------------------------------------------------
410 // Streaming support
411 // ------------------------------------------------------------------------
412
413 private synchronized void initializeStreamingMonitor() {
414
415 if (fInitialized) {
416 return;
417 }
418 fInitialized = true;
419
420 if (getStreamingInterval() == 0) {
421 final ITmfContext context = seekEvent(0);
422 final ITmfEvent event = getNext(context);
423 if (event == null)
424 return;
425 final TmfTimeRange timeRange = new TmfTimeRange(event.getTimestamp().clone(), TmfTimestamp.BIG_CRUNCH);
426 final TmfExperimentRangeUpdatedSignal signal = new TmfExperimentRangeUpdatedSignal(this, this, timeRange);
427
428 // Broadcast in separate thread to prevent deadlock
429 new Thread() {
430 @Override
431 public void run() {
432 broadcast(signal);
433 }
434 }.start();
435 return;
436 }
437
438 final Thread thread = new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
439 private ITmfTimestamp safeTimestamp = null;
440 private TmfTimeRange timeRange = null;
441
442 @Override
443 public void run() {
444 while (!fExecutor.isShutdown()) {
445 if (!getIndexer().isIndexing()) {
446 ITmfTimestamp startTimestamp = TmfTimestamp.BIG_CRUNCH;
447 ITmfTimestamp endTimestamp = TmfTimestamp.BIG_BANG;
448 for (final ITmfTrace<T> trace : fTraces) {
449 if (trace.getStartTime().compareTo(startTimestamp) < 0)
450 startTimestamp = trace.getStartTime();
451 if (trace.getStreamingInterval() != 0 && trace.getEndTime().compareTo(endTimestamp) > 0)
452 endTimestamp = trace.getEndTime();
453 }
454 if (safeTimestamp != null && safeTimestamp.compareTo(getTimeRange().getEndTime(), false) > 0)
455 timeRange = new TmfTimeRange(startTimestamp, safeTimestamp);
456 else
457 timeRange = null;
458 safeTimestamp = endTimestamp;
459 if (timeRange != null) {
460 final TmfExperimentRangeUpdatedSignal signal =
461 new TmfExperimentRangeUpdatedSignal(TmfExperiment.this, TmfExperiment.this, timeRange);
462 broadcast(signal);
463 }
464 }
465 try {
466 Thread.sleep(getStreamingInterval());
467 } catch (final InterruptedException e) {
468 e.printStackTrace();
469 }
470 }
471 }
472 };
473 thread.start();
474 }
475
476 /* (non-Javadoc)
477 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
478 */
479 @Override
480 public long getStreamingInterval() {
481 long interval = 0;
482 for (final ITmfTrace<T> trace : fTraces)
483 interval = Math.max(interval, trace.getStreamingInterval());
484 return interval;
485 }
486
487 // ------------------------------------------------------------------------
488 // Signal handlers
489 // ------------------------------------------------------------------------
490
491 private Integer fEndSynchReference;
492
493 /**
494 * Signal handler for the TmfExperimentSelectedSignal signal
495 *
496 * @param signal
497 */
498 @TmfSignalHandler
499 public void experimentSelected(final TmfExperimentSelectedSignal<T> signal) {
500 final TmfExperiment<?> experiment = signal.getExperiment();
501 if (experiment == this) {
502 setCurrentExperiment(experiment);
503 fEndSynchReference = Integer.valueOf(signal.getReference());
504 }
505 }
506
507 /**
508 * Signal handler for the TmfEndSynchSignal signal
509 *
510 * @param signal
511 */
512 @TmfSignalHandler
513 public void endSync(final TmfEndSynchSignal signal) {
514 if (fEndSynchReference != null && fEndSynchReference.intValue() == signal.getReference()) {
515 fEndSynchReference = null;
516 initializeStreamingMonitor();
517 }
518 }
519
520 /**
521 * Signal handler for the TmfTraceUpdatedSignal signal
522 *
523 * @param signal
524 */
525 @TmfSignalHandler
526 public void traceUpdated(final TmfTraceUpdatedSignal signal) {
527 if (signal.getTrace() == this) {
528 broadcast(new TmfExperimentUpdatedSignal(this, this));
529 }
530 }
531
532 /**
533 * Signal handler for the TmfExperimentRangeUpdatedSignal signal
534 *
535 * @param signal
536 */
537 @TmfSignalHandler
538 public void experimentRangeUpdated(final TmfExperimentRangeUpdatedSignal signal) {
539 if (signal.getExperiment() == this) {
540 getIndexer().buildIndex(getNbEvents(), signal.getRange(), false);
541 }
542 }
543
544 }
This page took 0.043432 seconds and 6 git commands to generate.