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