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