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