1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 Ericsson
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
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
;
15 import java
.util
.HashMap
;
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
;
46 public class StateExperimentManager
extends LTTngTreeNode
implements ILttExperimentSelectedListener
,
47 IStateExperimentManager
{
49 // ========================================================================
51 // =======================================================================
52 private LTTngTreeNode fSelectedExperiment
= null; // one selected experiment
54 private final StateExperimentListener fexperimentListener
;
55 private boolean fwaitForCompletion
= false;
57 * Used to route incoming events to proper trace manager, during check point building
59 private final Map
<ITmfTrace
, StateTraceHelper
> ftraceToManagerMap
= new HashMap
<ITmfTrace
, StateTraceHelper
>();
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;
71 // ========================================================================
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);
81 @SuppressWarnings({ "unchecked", "rawtypes" })
82 public void experimentSelected(TmfExperimentSelectedSignal signal
) {
83 experimentSelected_prep(signal
.getExperiment());
86 // ========================================================================
88 // =======================================================================
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)
93 // public ILttngSyntEventRequest readExperimentTimeWindow(TmfTimeRange trange,
94 // Object source, IRequestStatusListener listener,
95 // ITransEventProcessor processor) {
97 // ILttngSyntEventRequest request = null;
100 // if (fSelectedExperiment != null) {
101 // // Get all trace manager nodes
102 // LTTngTreeNode[] traceMgrs = fSelectedExperiment.getChildren();
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,
115 // if (fSelectedExperiment == null) {
116 // TraceDebug.debug("No experiment selected");
124 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperiment(java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
126 // @SuppressWarnings("unchecked")
127 // public void readExperiment(Object source, IRequestStatusListener listener,
128 // ITransEventProcessor processor) {
130 // if (fSelectedExperiment != null) {
131 // TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fSelectedExperiment
133 // TmfTimeRange trange = experiment.getTimeRange();
134 // readExperimentTimeWindow(trange, source, listener, processor);
136 // TraceDebug.debug("No selected experiment available");
143 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #experimentSelected_prep
144 * (org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
147 public void experimentSelected_prep(TmfExperiment experiment
) {
149 if (fSelectedExperiment
!= null) {
150 clearExperimentNode(fSelectedExperiment
);
151 fSelectedExperiment
= null;
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;
163 // Make sure all traces involved have a corresponding state manager
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
);
173 // Make sure the traces exists in the tree
174 ITmfTrace
[] rtraces
= experiment
.getTraces();
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
183 if (traceStateManagerNode
== null) {
184 traceStateManagerNode
= StateManagerFactory
.getManager(rtrace
, experimentNode
);
185 experimentNode
.addChild(traceStateManagerNode
);
189 // Reset event provider to handle requests for the new experiment
190 LttngCoreProviderFactory
.reset(experimentNode
);
192 // preserve the selected experiment
193 fSelectedExperiment
= experimentNode
;
197 private void clearExperimentNode(LTTngTreeNode experimentNode
) {
198 // Remove checkpoints
199 LTTngTreeNode
[] traceNodes
= experimentNode
.getChildren();
201 for (LTTngTreeNode traceStateManagerNode
: traceNodes
) {
202 IStateTraceManager traceManager
= null;
204 traceManager
= (IStateTraceManager
) traceStateManagerNode
;
205 // Clear all previously created check points as preparation to
207 traceManager
.clearCheckPoints();
208 experimentNode
.removeChild(traceStateManagerNode
);
209 } catch (ClassCastException e
) {
213 // rebuild the experiment nodes from scratch
214 removeChild(experimentNode
);
221 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentSelected(java.lang.Object,
222 * org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
225 public void experimentSelected(Object source
, TmfExperiment experiment
) {
227 if (experiment
== null) {
228 TraceDebug
.debug("Received experiment is null"); //$NON-NLS-1$
232 // If previous request is ongoing, cancel it before requesting a new
234 if (fStateCheckPointRequest
!= null && !fStateCheckPointRequest
.isCompleted()) {
235 fStateCheckPointRequest
.cancel();
238 synchronized (fCheckPointUpdateSyncObj
) {
239 fCheckPointUpdateBusy
= false;
240 fCheckPointUpdatePending
= false;
241 fCheckPointUpdateIndex
= 0;
250 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentUpdated
251 * (org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal, boolean)
253 @SuppressWarnings("unchecked")
255 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
256 TmfExperiment experiment
= signal
.getExperiment();
258 if (fSelectedExperiment
== null || experiment
!= fSelectedExperiment
.getValue()) {
262 synchronized (fCheckPointUpdateSyncObj
) {
263 if (fCheckPointUpdateBusy
) {
264 fCheckPointUpdatePending
= true;
265 fCheckPointUpdateRange
= signal
.getRange();
268 fCheckPointUpdateBusy
= true;
272 // If previous request is ongoing, cancel it before requesting a new
274 if (fStateCheckPointRequest
!= null && !fStateCheckPointRequest
.isCompleted()) {
275 fStateCheckPointRequest
.cancel();
278 // trigger data request to build the state system check points
279 fStateCheckPointRequest
= buildCheckPoints(experiment
, signal
.getRange(), fInitial
);
282 if (fStateCheckPointRequest
== null) {
283 synchronized (fCheckPointUpdateSyncObj
) {
284 fCheckPointUpdateBusy
= false;
290 * @return the SelectedExperiment tree node
293 public LTTngTreeNode
getSelectedExperiment() {
294 return fSelectedExperiment
;
300 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#getExperimentTimeRange()
303 @SuppressWarnings("unchecked")
304 public TmfTimeRange
getExperimentTimeRange() {
305 TmfTimeRange timeRangeResult
= null;
306 if (fSelectedExperiment
!= null) {
307 timeRangeResult
= ((TmfExperiment
) fSelectedExperiment
.getValue()).getTimeRange();
309 return timeRangeResult
;
315 * @see java.lang.Object#finalize()
318 protected void finalize() {
319 fexperimentListener
.dispose();
325 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #waitForComplete(boolean)
328 public void waitForCompletion(boolean wait
) {
329 fwaitForCompletion
= wait
;
332 private ITmfDataRequest
buildCheckPoints(final TmfExperiment experiment
,
333 final TmfTimeRange range
, boolean initial
) {
335 if (experiment
== null) {
336 TraceDebug
.debug("Received experiment is null"); //$NON-NLS-1$
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$
346 final boolean waitForCompletion
= fwaitForCompletion
;
348 // get the trace manager nodes associated to the experiment
349 LTTngTreeNode
[] traceNodes
= experimentNode
.getChildren();
352 synchronized (this) {
353 ftraceToManagerMap
.clear();
357 for (LTTngTreeNode traceStateManagerNode
: traceNodes
) {
358 IStateTraceManager traceManager
;
360 traceManager
= (IStateTraceManager
) traceStateManagerNode
;
361 } catch (ClassCastException e
) {
362 Activator
.getDefault().logError("Unexpected Error", e
); //$NON-NLS-1$
366 // Clear all previously created check points as preparation to
368 traceManager
.clearCheckPoints();
370 // build the trace to manager mapping for event dispatching
371 trace
= traceManager
.getStateTrace();
372 synchronized (this) {
373 ftraceToManagerMap
.put(trace
, new StateTraceHelper(traceManager
));
378 // if no trace mapping
379 if (ftraceToManagerMap
.size() < 1) {
380 TraceDebug
.debug("No traces associated to experiment " + experiment
.getName()); //$NON-NLS-1$
384 fCheckPointNbEventsHandled
= 0;
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
) {
394 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData()
397 public void handleData(ITmfEvent event
) {
398 super.handleData(event
);
400 // Tracer.trace("Chk: " + event.getTimestamp());
401 fCheckPointNbEventsHandled
++;
402 ITmfTrace trace
= event
.getTrace();
404 StateTraceHelper helper
= ftraceToManagerMap
.get(trace
);
406 if (helper
!= null) {
407 helper
.incrementNumberRead();
409 // obtain synthetic event
410 LttngSyntheticEvent synEvent
= updateSynEvent(event
, helper
.getTraceModel());
412 // update state system, and save check points as needed
413 helper
.getStateManager().handleEvent(synEvent
, helper
.getNumberRead());
415 TraceDebug
.debug("StateTraceManager not found for trace" //$NON-NLS-1$
424 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted()
427 public void handleCompleted() {
428 super.handleCompleted();
429 printCompletedMessage();
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);
449 private void printCompletedMessage() {
450 if (TraceDebug
.isDEBUG()) {
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$
460 // Execute event data request
461 experiment
.sendRequest(request
);
463 if (waitForCompletion
) {
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);
475 } catch (InterruptedException e
) {
482 private LttngSyntheticEvent
updateSynEvent(ITmfEvent e
, LttngTraceState stateModel
) {
483 if (syntheticEvent
== null || syntheticEvent
.getBaseEvent() != e
) {
484 syntheticEvent
= new LttngSyntheticEvent(e
);
487 // Trace model needed by application handlers
488 syntheticEvent
.setTraceModel(stateModel
);
489 syntheticEvent
.setSequenceInd(SequenceInd
.UPDATE
);
491 return syntheticEvent
;
496 * Helper class that wraps the StateTraceManager, the current LTTngTraceState and the number of read events
501 private static class StateTraceHelper
{
503 IStateTraceManager stateTraceManager
= null;
504 long numberEventsRead
= 0;
505 LttngTraceState stateTraceModel
= null;
510 * @param stateManager
511 * The StateTraceManager the helper is for
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();
521 * Returns the StateTraceManager
523 * @return IStateTraceManager
525 public IStateTraceManager
getStateManager() {
526 return stateTraceManager
;
530 * Returns the number of read events
534 public long getNumberRead() {
535 return numberEventsRead
;
539 * Increments the number of read events
541 public void incrementNumberRead() {
546 * Returns the current LTTngTraceState
548 * @return LttngTraceState
550 public LttngTraceState
getTraceModel() {
551 return stateTraceModel
;