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