tmf: Use tabs in statistics view for each traces
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.core / src / org / eclipse / linuxtools / internal / lttng / core / state / experiment / StateExperimentManager.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 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 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 * Marc Dumais (marc.dumais@ericsson.com) - Fix for 316455 (second part)
12 *******************************************************************************/
13 package org.eclipse.linuxtools.internal.lttng.core.state.experiment;
14
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import org.eclipse.linuxtools.internal.lttng.core.Activator;
19 import org.eclipse.linuxtools.internal.lttng.core.LttngConstants;
20 import org.eclipse.linuxtools.internal.lttng.core.TraceDebug;
21 import org.eclipse.linuxtools.internal.lttng.core.control.LttngCoreProviderFactory;
22 import org.eclipse.linuxtools.internal.lttng.core.event.LttngEvent;
23 import org.eclipse.linuxtools.internal.lttng.core.event.LttngSyntheticEvent;
24 import org.eclipse.linuxtools.internal.lttng.core.event.LttngSyntheticEvent.SequenceInd;
25 import org.eclipse.linuxtools.internal.lttng.core.model.LTTngTreeNode;
26 import org.eclipse.linuxtools.internal.lttng.core.signal.ILttExperimentSelectedListener;
27 import org.eclipse.linuxtools.internal.lttng.core.signal.StateExperimentListener;
28 import org.eclipse.linuxtools.internal.lttng.core.state.model.LttngTraceState;
29 import org.eclipse.linuxtools.internal.lttng.core.state.trace.IStateTraceManager;
30 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
31 import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
32 import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
33 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
34 import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
35 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
36 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
37 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
38 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
39 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
40 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
41
42 /**
43 * @author alvaro
44 *
45 */
46 public class StateExperimentManager extends LTTngTreeNode implements ILttExperimentSelectedListener,
47 IStateExperimentManager {
48
49 // ========================================================================
50 // Data
51 // =======================================================================
52 private LTTngTreeNode fSelectedExperiment = null; // one selected experiment
53 // supported
54 private final StateExperimentListener fexperimentListener;
55 private boolean fwaitForCompletion = false;
56 /**
57 * Used to route incoming events to proper trace manager, during check point building
58 */
59 private final Map<ITmfTrace, StateTraceHelper> ftraceToManagerMap = new HashMap<ITmfTrace, StateTraceHelper>();
60
61 private LttngSyntheticEvent syntheticEvent = null;
62 private ITmfDataRequest fStateCheckPointRequest = null;
63 private boolean fCheckPointUpdateBusy = false;
64 private boolean fCheckPointUpdatePending = false;
65 private int fCheckPointUpdateIndex = 0;
66 private TmfTimeRange fCheckPointUpdateRange = null;
67 private long fCheckPointNbEventsHandled = 0;
68 private final Object fCheckPointUpdateSyncObj = new Object();
69 private boolean fInitial = false;
70
71 // ========================================================================
72 // Constructors
73 // =======================================================================
74 public StateExperimentManager(Long id, String name) {
75 super(id, null, name, null);
76 fexperimentListener = new StateExperimentListener("Experiment Manager", this); //$NON-NLS-1$
77 TmfSignalManager.registerVIP(this);
78 }
79
80 @TmfSignalHandler
81 @SuppressWarnings({ "unchecked", "rawtypes" })
82 public void experimentSelected(TmfExperimentSelectedSignal signal) {
83 experimentSelected_prep(signal.getExperiment());
84 }
85
86 // ========================================================================
87 // Methods
88 // =======================================================================
89
90 // /* (non-Javadoc)
91 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperimentTimeWindow(org.eclipse.linuxtools.tmf.event.TmfTimeRange, java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
92 // */
93 // public ILttngSyntEventRequest readExperimentTimeWindow(TmfTimeRange trange,
94 // Object source, IRequestStatusListener listener,
95 // ITransEventProcessor processor) {
96 //
97 // ILttngSyntEventRequest request = null;
98 //
99 // // validate
100 // if (fSelectedExperiment != null) {
101 // // Get all trace manager nodes
102 // LTTngTreeNode[] traceMgrs = fSelectedExperiment.getChildren();
103 //
104 // if (traceMgrs != null && traceMgrs.length > 0) {
105 // IStateTraceManager traceManager;
106 // // Trigger one request per trace
107 // for (LTTngTreeNode traceNode : traceMgrs) {
108 // traceManager = (IStateTraceManager) traceNode;
109 // request = traceManager.executeDataRequest(trange, source,
110 // listener,
111 // processor);
112 // }
113 // }
114 // } else {
115 // if (fSelectedExperiment == null) {
116 // TraceDebug.debug("No experiment selected");
117 // }
118 // }
119 //
120 // return request;
121 // }
122
123 // /* (non-Javadoc)
124 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperiment(java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
125 // */
126 // @SuppressWarnings("unchecked")
127 // public void readExperiment(Object source, IRequestStatusListener listener,
128 // ITransEventProcessor processor) {
129 // // validate
130 // if (fSelectedExperiment != null) {
131 // TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fSelectedExperiment
132 // .getValue();
133 // TmfTimeRange trange = experiment.getTimeRange();
134 // readExperimentTimeWindow(trange, source, listener, processor);
135 // } else {
136 // TraceDebug.debug("No selected experiment available");
137 // }
138 // }
139
140 /*
141 * (non-Javadoc)
142 *
143 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #experimentSelected_prep
144 * (org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
145 */
146 @Override
147 public void experimentSelected_prep(TmfExperiment experiment) {
148
149 if (fSelectedExperiment != null) {
150 clearExperimentNode(fSelectedExperiment);
151 fSelectedExperiment = null;
152 }
153
154 LTTngTreeNode experimentNode = null;
155 if (experiment != null) {
156 experimentNode = getChildByName(experiment.getName());
157 // keep experiment if already loaded with the same value
158 if (experimentNode != null && experimentNode.getValue() != experiment) {
159 clearExperimentNode(experimentNode);
160 experimentNode = null;
161 }
162
163 // Make sure all traces involved have a corresponding state manager
164 // and
165 // state system to request its initial data
166 if (experimentNode == null) {
167 // Create the new experiment tree node
168 experimentNode = new LTTngTreeNode(getNextUniqueId(), this, experiment.getName(), experiment);
169 // add the new experiment to this children list
170 addChild(experimentNode);
171 }
172
173 // Make sure the traces exists in the tree
174 ITmfTrace[] rtraces = experiment.getTraces();
175 String traceName;
176 LTTngTreeNode traceStateManagerNode;
177 // StateStacksHandler
178 for (ITmfTrace rtrace : rtraces) {
179 traceName = rtrace.getName();
180 traceStateManagerNode = experimentNode.getChildByName(traceName);
181 // Node does not exist for this experiment, so needs to be
182 // created
183 if (traceStateManagerNode == null) {
184 traceStateManagerNode = StateManagerFactory.getManager(rtrace, experimentNode);
185 experimentNode.addChild(traceStateManagerNode);
186 }
187 }
188
189 // Reset event provider to handle requests for the new experiment
190 LttngCoreProviderFactory.reset(experimentNode);
191
192 // preserve the selected experiment
193 fSelectedExperiment = experimentNode;
194 }
195 }
196
197 private void clearExperimentNode(LTTngTreeNode experimentNode) {
198 // Remove checkpoints
199 LTTngTreeNode[] traceNodes = experimentNode.getChildren();
200
201 for (LTTngTreeNode traceStateManagerNode : traceNodes) {
202 IStateTraceManager traceManager = null;
203 try {
204 traceManager = (IStateTraceManager) traceStateManagerNode;
205 // Clear all previously created check points as preparation to
206 // re-build
207 traceManager.clearCheckPoints();
208 experimentNode.removeChild(traceStateManagerNode);
209 } catch (ClassCastException e) {
210 // Nothing to do
211 }
212
213 // rebuild the experiment nodes from scratch
214 removeChild(experimentNode);
215 }
216 }
217
218 /*
219 * (non-Javadoc)
220 *
221 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentSelected(java.lang.Object,
222 * org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
223 */
224 @Override
225 public void experimentSelected(Object source, TmfExperiment experiment) {
226 // validate
227 if (experiment == null) {
228 TraceDebug.debug("Received experiment is null"); //$NON-NLS-1$
229 return;
230 }
231
232 // If previous request is ongoing, cancel it before requesting a new
233 // one.
234 if (fStateCheckPointRequest != null && !fStateCheckPointRequest.isCompleted()) {
235 fStateCheckPointRequest.cancel();
236 }
237
238 synchronized (fCheckPointUpdateSyncObj) {
239 fCheckPointUpdateBusy = false;
240 fCheckPointUpdatePending = false;
241 fCheckPointUpdateIndex = 0;
242 }
243
244 fInitial = true;
245 }
246
247 /*
248 * (non-Javadoc)
249 *
250 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentUpdated
251 * (org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal, boolean)
252 */
253 @SuppressWarnings("unchecked")
254 @Override
255 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
256 TmfExperiment experiment = signal.getExperiment();
257 // validate
258 if (fSelectedExperiment == null || experiment != fSelectedExperiment.getValue()) {
259 return;
260 }
261
262 synchronized (fCheckPointUpdateSyncObj) {
263 if (fCheckPointUpdateBusy) {
264 fCheckPointUpdatePending = true;
265 fCheckPointUpdateRange = signal.getRange();
266 return;
267 } else {
268 fCheckPointUpdateBusy = true;
269 }
270 }
271
272 // If previous request is ongoing, cancel it before requesting a new
273 // one.
274 if (fStateCheckPointRequest != null && !fStateCheckPointRequest.isCompleted()) {
275 fStateCheckPointRequest.cancel();
276 }
277
278 // trigger data request to build the state system check points
279 fStateCheckPointRequest = buildCheckPoints(experiment, signal.getRange(), fInitial);
280 fInitial = false;
281
282 if (fStateCheckPointRequest == null) {
283 synchronized (fCheckPointUpdateSyncObj) {
284 fCheckPointUpdateBusy = false;
285 }
286 }
287 }
288
289 /**
290 * @return the SelectedExperiment tree node
291 */
292 @Override
293 public LTTngTreeNode getSelectedExperiment() {
294 return fSelectedExperiment;
295 }
296
297 /*
298 * (non-Javadoc)
299 *
300 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#getExperimentTimeRange()
301 */
302 @Override
303 @SuppressWarnings("unchecked")
304 public TmfTimeRange getExperimentTimeRange() {
305 TmfTimeRange timeRangeResult = null;
306 if (fSelectedExperiment != null) {
307 timeRangeResult = ((TmfExperiment) fSelectedExperiment.getValue()).getTimeRange();
308 }
309 return timeRangeResult;
310 }
311
312 /*
313 * (non-Javadoc)
314 *
315 * @see java.lang.Object#finalize()
316 */
317 @Override
318 protected void finalize() {
319 fexperimentListener.dispose();
320 }
321
322 /*
323 * (non-Javadoc)
324 *
325 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #waitForComplete(boolean)
326 */
327 @Override
328 public void waitForCompletion(boolean wait) {
329 fwaitForCompletion = wait;
330 }
331
332 private ITmfDataRequest buildCheckPoints(final TmfExperiment experiment,
333 final TmfTimeRange range, boolean initial) {
334 // validate
335 if (experiment == null) {
336 TraceDebug.debug("Received experiment is null"); //$NON-NLS-1$
337 return null;
338 }
339
340 LTTngTreeNode experimentNode = getChildByName(experiment.getName());
341 if (experimentNode == null) {
342 TraceDebug.debug("Experiment Node " + experiment.getName() + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
343 return null;
344 }
345
346 final boolean waitForCompletion = fwaitForCompletion;
347
348 // get the trace manager nodes associated to the experiment
349 LTTngTreeNode[] traceNodes = experimentNode.getChildren();
350
351 if (initial) {
352 synchronized (this) {
353 ftraceToManagerMap.clear();
354 }
355
356 ITmfTrace trace;
357 for (LTTngTreeNode traceStateManagerNode : traceNodes) {
358 IStateTraceManager traceManager;
359 try {
360 traceManager = (IStateTraceManager) traceStateManagerNode;
361 } catch (ClassCastException e) {
362 Activator.getDefault().logError("Unexpected Error", e); //$NON-NLS-1$
363 return null;
364 }
365
366 // Clear all previously created check points as preparation to
367 // re-build
368 traceManager.clearCheckPoints();
369
370 // build the trace to manager mapping for event dispatching
371 trace = traceManager.getStateTrace();
372 synchronized (this) {
373 ftraceToManagerMap.put(trace, new StateTraceHelper(traceManager));
374 }
375 }
376 }
377
378 // if no trace mapping
379 if (ftraceToManagerMap.size() < 1) {
380 TraceDebug.debug("No traces associated to experiment " + experiment.getName()); //$NON-NLS-1$
381 return null;
382 }
383
384 fCheckPointNbEventsHandled = 0;
385
386 // Prepare event data request to build state model
387 ITmfEventRequest request = new TmfEventRequest(LttngEvent.class, range,
388 fCheckPointUpdateIndex, TmfEventRequest.ALL_DATA, LttngConstants.DEFAULT_BLOCK_SIZE,
389 ITmfDataRequest.ExecutionType.BACKGROUND) {
390
391 /*
392 * (non-Javadoc)
393 *
394 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData()
395 */
396 @Override
397 public void handleData(ITmfEvent event) {
398 super.handleData(event);
399 if (event != null) {
400 // Tracer.trace("Chk: " + event.getTimestamp());
401 fCheckPointNbEventsHandled++;
402 ITmfTrace trace = event.getTrace();
403
404 StateTraceHelper helper = ftraceToManagerMap.get(trace);
405
406 if (helper != null) {
407 helper.incrementNumberRead();
408
409 // obtain synthetic event
410 LttngSyntheticEvent synEvent = updateSynEvent(event, helper.getTraceModel());
411
412 // update state system, and save check points as needed
413 helper.getStateManager().handleEvent(synEvent, helper.getNumberRead());
414 } else {
415 TraceDebug.debug("StateTraceManager not found for trace" //$NON-NLS-1$
416 + trace.getName());
417 }
418 }
419 }
420
421 /*
422 * (non-Javadoc)
423 *
424 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted()
425 */
426 @Override
427 public void handleCompleted() {
428 super.handleCompleted();
429 printCompletedMessage();
430
431 if (!waitForCompletion) {
432 synchronized (fCheckPointUpdateSyncObj) {
433 fCheckPointUpdateBusy = false;
434 fCheckPointUpdateIndex += fCheckPointNbEventsHandled;
435 if (fCheckPointUpdatePending) {
436 fCheckPointUpdatePending = false;
437 fCheckPointUpdateBusy = true;
438 buildCheckPoints(experiment, fCheckPointUpdateRange, false);
439 }
440 }
441 }
442 }
443
444 /*
445 * /**
446 *
447 * @param header
448 */
449 private void printCompletedMessage() {
450 if (TraceDebug.isDEBUG()) {
451 TraceDebug
452 .debug("Trace check point building completed, number of events handled: " + fCheckPointNbEventsHandled + "\n\t\t"); //$NON-NLS-1$ //$NON-NLS-2$
453 for (StateTraceHelper helper : ftraceToManagerMap.values()) {
454 TraceDebug.debug(helper.getStateManager().toString() + "\n\t\t"); //$NON-NLS-1$
455 }
456 }
457 }
458 };
459
460 // Execute event data request
461 experiment.sendRequest(request);
462
463 if (waitForCompletion) {
464 try {
465 request.waitForCompletion();
466 synchronized (fCheckPointUpdateSyncObj) {
467 fCheckPointUpdateBusy = false;
468 fCheckPointUpdateIndex += fCheckPointNbEventsHandled;
469 if (fCheckPointUpdatePending) {
470 fCheckPointUpdatePending = false;
471 fCheckPointUpdateBusy = true;
472 buildCheckPoints(experiment, fCheckPointUpdateRange, false);
473 }
474 }
475 } catch (InterruptedException e) {
476 }
477 }
478
479 return request;
480 }
481
482 private LttngSyntheticEvent updateSynEvent(ITmfEvent e, LttngTraceState stateModel) {
483 if (syntheticEvent == null || syntheticEvent.getBaseEvent() != e) {
484 syntheticEvent = new LttngSyntheticEvent(e);
485 }
486
487 // Trace model needed by application handlers
488 syntheticEvent.setTraceModel(stateModel);
489 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
490
491 return syntheticEvent;
492 }
493
494
495 /**
496 * Helper class that wraps the StateTraceManager, the current LTTngTraceState and the number of read events
497 *
498 * @author bHufmann
499 *
500 */
501 private static class StateTraceHelper {
502
503 IStateTraceManager stateTraceManager = null;
504 long numberEventsRead = 0;
505 LttngTraceState stateTraceModel = null;
506
507 /**
508 * Constructor
509 *
510 * @param stateManager
511 * The StateTraceManager the helper is for
512 */
513 public StateTraceHelper(IStateTraceManager stateManager) {
514 this.stateTraceManager = stateManager;
515 // Get the TraceState at the beginning of the trace
516 this.stateTraceManager.restoreCheckPointByTimestamp(stateManager.getStateTrace().getStartTime());
517 this.stateTraceModel = this.stateTraceManager.getStateModel();
518 }
519
520 /**
521 * Returns the StateTraceManager
522 *
523 * @return IStateTraceManager
524 */
525 public IStateTraceManager getStateManager() {
526 return stateTraceManager;
527 }
528
529 /**
530 * Returns the number of read events
531 *
532 * @return long
533 */
534 public long getNumberRead() {
535 return numberEventsRead;
536 }
537
538 /**
539 * Increments the number of read events
540 */
541 public void incrementNumberRead() {
542 ++numberEventsRead;
543 }
544
545 /**
546 * Returns the current LTTngTraceState
547 *
548 * @return LttngTraceState
549 */
550 public LttngTraceState getTraceModel() {
551 return stateTraceModel;
552 }
553 }
554 }
This page took 0.047937 seconds and 5 git commands to generate.