0b0bebf039e6a5fafcaa1e3ed19c6ae712a9877d
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfExperiment.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 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.exceptions.TmfTraceException;
26 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
27 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
28 import org.eclipse.linuxtools.tmf.core.signal.TmfClearExperimentSignal;
29 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
31 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
32 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
33 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
34 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
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 @Override
195 public ITmfTrace[] getTraces() {
196 return fTraces;
197 }
198
199 /**
200 * Returns the timestamp of the event at the requested index. If none,
201 * returns null.
202 *
203 * @param index the event index (rank)
204 * @return the corresponding event timestamp
205 * @since 2.0
206 */
207 public ITmfTimestamp getTimestamp(final int index) {
208 final ITmfContext context = seekEvent(index);
209 final ITmfEvent event = getNext(context);
210 context.dispose();
211 return (event != null) ? event.getTimestamp() : null;
212 }
213
214 /**
215 * Set the file to be used for bookmarks on this experiment
216 *
217 * @param file the bookmarks file
218 */
219 public void setBookmarksFile(final IFile file) {
220 fBookmarksFile = file;
221 }
222
223 /**
224 * Get the file used for bookmarks on this experiment
225 *
226 * @return the bookmarks file or null if none is set
227 */
228 public IFile getBookmarksFile() {
229 return fBookmarksFile;
230 }
231
232 // ------------------------------------------------------------------------
233 // Request management
234 // ------------------------------------------------------------------------
235
236 /**
237 * @since 2.0
238 */
239 @Override
240 public synchronized ITmfContext armRequest(final ITmfDataRequest request) {
241
242 // Make sure we have something to read from
243 if (fTraces == null) {
244 return null;
245 }
246
247 if (request instanceof ITmfEventRequest
248 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest) request).getRange().getStartTime())
249 && request.getIndex() == 0)
250 {
251 final ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime());
252 ((ITmfEventRequest) request).setStartIndex((int) context.getRank());
253 return context;
254
255 }
256
257 return seekEvent(request.getIndex());
258 }
259
260 // ------------------------------------------------------------------------
261 // ITmfTrace trace positioning
262 // ------------------------------------------------------------------------
263
264 /* (non-Javadoc)
265 *
266 * Returns a brand new context based on the location provided and
267 * initializes the event queues
268 *
269 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfLocation)
270 */
271 @Override
272 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
273 // Validate the location
274 if (location != null && !(location instanceof TmfExperimentLocation)) {
275 return null; // Throw an exception?
276 }
277 // Make sure we have something to read from
278 if (fTraces == null) {
279 return null;
280 }
281
282 // Initialize the location array if necessary
283 TmfLocationArray locationArray = ((location == null) ?
284 new TmfLocationArray(fTraces.length) :
285 ((TmfExperimentLocation) location).getLocationInfo());
286
287 ITmfLocation[] locations = locationArray.getLocations();
288 long[] ranks = locationArray.getRanks();
289
290 // Create and populate the context's traces contexts
291 final TmfExperimentContext context = new TmfExperimentContext(fTraces.length);
292
293 // Position the traces
294 long rank = 0;
295 for (int i = 0; i < fTraces.length; i++) {
296 // Get the relevant trace attributes
297 final ITmfContext traceContext = fTraces[i].seekEvent(locations[i]);
298 context.getContexts()[i] = traceContext;
299 traceContext.setRank(ranks[i]);
300 locations[i] = traceContext.getLocation(); // update location after seek
301 context.getEvents()[i] = fTraces[i].getNext(traceContext);
302 rank += ranks[i];
303 }
304
305 // Finalize context
306 context.setLocation(new TmfExperimentLocation(new TmfLocationArray(locations, ranks)));
307 context.setLastTrace(TmfExperimentContext.NO_TRACE);
308 context.setRank(rank);
309
310 return context;
311 }
312
313 // ------------------------------------------------------------------------
314 // ITmfTrace - SeekEvent operations (returning a trace context)
315 // ------------------------------------------------------------------------
316
317 /* (non-Javadoc)
318 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(double)
319 */
320 @Override
321 public ITmfContext seekEvent(final double ratio) {
322 final ITmfContext context = seekEvent(Math.round(ratio * getNbEvents()));
323 return context;
324 }
325
326 /* (non-Javadoc)
327 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getLocationRatio(org.eclipse.linuxtools.tmf.core.trace.ITmfLocation)
328 */
329 @Override
330 public double getLocationRatio(final ITmfLocation location) {
331 if (location instanceof TmfExperimentLocation) {
332 long rank = 0;
333 TmfLocationArray locationArray = ((TmfExperimentLocation) location).getLocationInfo();
334 for (int i = 0; i < locationArray.size(); i++) {
335 rank += locationArray.getRank(i);
336 }
337 return (double) rank / getNbEvents();
338 }
339 return 0.0;
340 }
341
342 /* (non-Javadoc)
343 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getCurrentLocation()
344 */
345 @Override
346 public ITmfLocation getCurrentLocation() {
347 // never used
348 return null;
349 }
350
351 // ------------------------------------------------------------------------
352 // ITmfTrace trace positioning
353 // ------------------------------------------------------------------------
354
355 /* (non-Javadoc)
356 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser#parseEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
357 */
358 @Override
359 public synchronized ITmfEvent parseEvent(final ITmfContext context) {
360 final ITmfContext tmpContext = seekEvent(context.getLocation());
361 final ITmfEvent event = getNext(tmpContext);
362 return event;
363 }
364
365 /* (non-Javadoc)
366 * @see org.eclipse.linuxtools.tmf.core.trace.TmfTrace#getNext(org.eclipse.linuxtools.tmf.core.trace.ITmfContext)
367 */
368 @Override
369 public synchronized ITmfEvent getNext(ITmfContext context) {
370
371 // Validate the context
372 if (!(context instanceof TmfExperimentContext)) {
373 return null; // Throw an exception?
374 }
375
376 // Make sure that we have something to read from
377 if (fTraces == null) {
378 return null;
379 }
380
381 TmfExperimentContext expContext = (TmfExperimentContext) context;
382
383 // If an event was consumed previously, first get the next one from that trace
384 final int lastTrace = expContext.getLastTrace();
385 if (lastTrace != TmfExperimentContext.NO_TRACE) {
386 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
387 expContext.getEvents()[lastTrace] = fTraces[lastTrace].getNext(traceContext);
388 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
389 }
390
391 // Scan the candidate events and identify the "next" trace to read from
392 int trace = TmfExperimentContext.NO_TRACE;
393 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
394 for (int i = 0; i < fTraces.length; i++) {
395 final ITmfEvent event = expContext.getEvents()[i];
396 if (event != null && event.getTimestamp() != null) {
397 final ITmfTimestamp otherTS = event.getTimestamp();
398 if (otherTS.compareTo(timestamp, true) < 0) {
399 trace = i;
400 timestamp = otherTS;
401 }
402 }
403 }
404
405 ITmfEvent event = null;
406 if (trace != TmfExperimentContext.NO_TRACE) {
407 event = expContext.getEvents()[trace];
408 if (event != null) {
409 updateAttributes(expContext, event.getTimestamp());
410 expContext.increaseRank();
411 expContext.setLastTrace(trace);
412 final ITmfContext traceContext = expContext.getContexts()[trace];
413
414 // Update the experiment location
415 TmfLocationArray locationArray = new TmfLocationArray(
416 ((TmfExperimentLocation) expContext.getLocation()).getLocationInfo(),
417 trace, traceContext.getLocation(), traceContext.getRank());
418 expContext.setLocation(new TmfExperimentLocation(locationArray));
419
420 processEvent(event);
421 }
422 }
423
424 return event;
425 }
426
427 /* (non-Javadoc)
428 * @see org.eclipse.linuxtools.tmf.core.trace.TmfTrace#getInitialRangeOffset()
429 */
430 /**
431 * @since 2.0
432 */
433 @Override
434 public ITmfTimestamp getInitialRangeOffset() {
435 if ((fTraces == null) || (fTraces.length == 0)) {
436 return super.getInitialRangeOffset();
437 }
438
439 ITmfTimestamp initTs = TmfTimestamp.BIG_CRUNCH;
440 for (int i = 0; i < fTraces.length; i++) {
441 ITmfTimestamp ts = fTraces[i].getInitialRangeOffset();
442 if (ts.compareTo(initTs) < 0) {
443 initTs = ts;
444 }
445 }
446 return initTs;
447 }
448
449 /* (non-Javadoc)
450 * @see java.lang.Object#toString()
451 */
452 @Override
453 @SuppressWarnings("nls")
454 public synchronized String toString() {
455 return "[TmfExperiment (" + getName() + ")]";
456 }
457
458 // ------------------------------------------------------------------------
459 // Streaming support
460 // ------------------------------------------------------------------------
461
462 private synchronized void initializeStreamingMonitor() {
463
464 if (fInitialized) {
465 return;
466 }
467 fInitialized = true;
468
469 if (getStreamingInterval() == 0) {
470 final ITmfContext context = seekEvent(0);
471 final ITmfEvent event = getNext(context);
472 context.dispose();
473 if (event == null) {
474 return;
475 }
476 final TmfTimeRange timeRange = new TmfTimeRange(event.getTimestamp(), TmfTimestamp.BIG_CRUNCH);
477 final TmfTraceRangeUpdatedSignal signal = new TmfTraceRangeUpdatedSignal(this, this, timeRange);
478
479 // Broadcast in separate thread to prevent deadlock
480 new Thread() {
481 @Override
482 public void run() {
483 broadcast(signal);
484 }
485 }.start();
486 return;
487 }
488
489 final Thread thread = new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
490 private ITmfTimestamp safeTimestamp = null;
491 private ITmfTimestamp lastSafeTimestamp = null;
492 private TmfTimeRange timeRange = null;
493
494 @Override
495 public void run() {
496 while (!executorIsShutdown()) {
497 if (!getIndexer().isIndexing()) {
498 ITmfTimestamp startTimestamp = TmfTimestamp.BIG_CRUNCH;
499 ITmfTimestamp endTimestamp = TmfTimestamp.BIG_BANG;
500 for (final ITmfTrace trace : fTraces) {
501 if (trace.getStartTime().compareTo(startTimestamp) < 0) {
502 startTimestamp = trace.getStartTime();
503 }
504 if (trace.getStreamingInterval() != 0 && trace.getEndTime().compareTo(endTimestamp) > 0) {
505 endTimestamp = trace.getEndTime();
506 }
507 }
508 if (safeTimestamp != null && (lastSafeTimestamp == null || safeTimestamp.compareTo(lastSafeTimestamp, false) > 0)) {
509 timeRange = new TmfTimeRange(startTimestamp, safeTimestamp);
510 lastSafeTimestamp = safeTimestamp;
511 } else {
512 timeRange = null;
513 }
514 safeTimestamp = endTimestamp;
515 if (timeRange != null) {
516 final TmfTraceRangeUpdatedSignal signal =
517 new TmfTraceRangeUpdatedSignal(TmfExperiment.this, TmfExperiment.this, timeRange);
518 broadcast(signal);
519 }
520 }
521 try {
522 Thread.sleep(getStreamingInterval());
523 } catch (final InterruptedException e) {
524 e.printStackTrace();
525 }
526 }
527 }
528 };
529 thread.start();
530 }
531
532 /* (non-Javadoc)
533 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
534 */
535 @Override
536 public long getStreamingInterval() {
537 long interval = 0;
538 for (final ITmfTrace trace : fTraces) {
539 interval = Math.max(interval, trace.getStreamingInterval());
540 }
541 return interval;
542 }
543
544 // ------------------------------------------------------------------------
545 // Signal handlers
546 // ------------------------------------------------------------------------
547
548 /* (non-Javadoc)
549 * @see org.eclipse.linuxtools.tmf.core.trace.TmfTrace#traceOpened(org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal)
550 */
551 @Override
552 @TmfSignalHandler
553 public void traceOpened(TmfTraceOpenedSignal signal) {
554 if (signal.getTrace() == this) {
555 initializeStreamingMonitor();
556 }
557 }
558
559 }
This page took 0.042202 seconds and 4 git commands to generate.