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
.lttng
.state
.experiment
;
15 import java
.util
.HashMap
;
18 import org
.eclipse
.linuxtools
.lttng
.LttngConstants
;
19 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
20 import org
.eclipse
.linuxtools
.lttng
.control
.LttngCoreProviderFactory
;
21 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
22 import org
.eclipse
.linuxtools
.lttng
.event
.LttngSyntheticEvent
;
23 import org
.eclipse
.linuxtools
.lttng
.event
.LttngSyntheticEvent
.SequenceInd
;
24 import org
.eclipse
.linuxtools
.lttng
.model
.LTTngTreeNode
;
25 import org
.eclipse
.linuxtools
.lttng
.signal
.ILttExperimentSelectedListener
;
26 import org
.eclipse
.linuxtools
.lttng
.signal
.StateExperimentListener
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTraceState
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.trace
.IStateTraceManager
;
29 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
30 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperiment
;
31 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfDataRequest
;
32 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfEventRequest
;
33 import org
.eclipse
.linuxtools
.tmf
.request
.TmfEventRequest
;
34 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentRangeUpdatedSignal
;
35 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentSelectedSignal
;
36 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
37 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalManager
;
38 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfTrace
;
44 public class StateExperimentManager
extends LTTngTreeNode
implements ILttExperimentSelectedListener
,
45 IStateExperimentManager
{
47 // ========================================================================
49 // =======================================================================
50 private LTTngTreeNode fSelectedExperiment
= null; // one selected experiment
52 private final StateExperimentListener fexperimentListener
;
53 private boolean fwaitForCompletion
= false;
55 * Used to route incoming events to proper trace manager, during check point building
57 private final Map
<ITmfTrace
, StateTraceHelper
> ftraceToManagerMap
= new HashMap
<ITmfTrace
, StateTraceHelper
>();
59 private LttngSyntheticEvent syntheticEvent
= null;
60 private ITmfDataRequest
<LttngEvent
> fStateCheckPointRequest
= null;
61 private boolean fCheckPointUpdateBusy
= false;
62 private boolean fCheckPointUpdatePending
= false;
63 private int fCheckPointUpdateIndex
= 0;
64 private TmfTimeRange fCheckPointUpdateRange
= null;
65 private long fCheckPointNbEventsHandled
= 0;
66 private final Object fCheckPointUpdateSyncObj
= new Object();
67 private boolean fInitial
= false;
69 // ========================================================================
71 // =======================================================================
72 public StateExperimentManager(Long id
, String name
) {
73 super(id
, null, name
, null);
74 fexperimentListener
= new StateExperimentListener("Experiment Manager", this); //$NON-NLS-1$
75 TmfSignalManager
.registerVIP(this);
79 @SuppressWarnings({ "unchecked", "rawtypes" })
80 public void experimentSelected(TmfExperimentSelectedSignal signal
) {
81 experimentSelected_prep(signal
.getExperiment());
84 // ========================================================================
86 // =======================================================================
89 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperimentTimeWindow(org.eclipse.linuxtools.tmf.event.TmfTimeRange, java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
91 // public ILttngSyntEventRequest readExperimentTimeWindow(TmfTimeRange trange,
92 // Object source, IRequestStatusListener listener,
93 // ITransEventProcessor processor) {
95 // ILttngSyntEventRequest request = null;
98 // if (fSelectedExperiment != null) {
99 // // Get all trace manager nodes
100 // LTTngTreeNode[] traceMgrs = fSelectedExperiment.getChildren();
102 // if (traceMgrs != null && traceMgrs.length > 0) {
103 // IStateTraceManager traceManager;
104 // // Trigger one request per trace
105 // for (LTTngTreeNode traceNode : traceMgrs) {
106 // traceManager = (IStateTraceManager) traceNode;
107 // request = traceManager.executeDataRequest(trange, source,
113 // if (fSelectedExperiment == null) {
114 // TraceDebug.debug("No experiment selected");
122 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperiment(java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
124 // @SuppressWarnings("unchecked")
125 // public void readExperiment(Object source, IRequestStatusListener listener,
126 // ITransEventProcessor processor) {
128 // if (fSelectedExperiment != null) {
129 // TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fSelectedExperiment
131 // TmfTimeRange trange = experiment.getTimeRange();
132 // readExperimentTimeWindow(trange, source, listener, processor);
134 // TraceDebug.debug("No selected experiment available");
141 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #experimentSelected_prep
142 * (org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
145 public void experimentSelected_prep(TmfExperiment
<LttngEvent
> experiment
) {
147 if (fSelectedExperiment
!= null) {
148 clearExperimentNode(fSelectedExperiment
);
149 fSelectedExperiment
= null;
152 LTTngTreeNode experimentNode
= null;
153 if (experiment
!= null) {
154 experimentNode
= getChildByName(experiment
.getName());
155 // keep experiment if already loaded with the same value
156 if (experimentNode
!= null && experimentNode
.getValue() != experiment
) {
157 clearExperimentNode(experimentNode
);
158 experimentNode
= null;
161 // Make sure all traces involved have a corresponding state manager
163 // state system to request its initial data
164 if (experimentNode
== null) {
165 // Create the new experiment tree node
166 experimentNode
= new LTTngTreeNode(getNextUniqueId(), this, experiment
.getName(), experiment
);
167 // add the new experiment to this children list
168 addChild(experimentNode
);
171 // Make sure the traces exists in the tree
172 ITmfTrace
[] rtraces
= experiment
.getTraces();
174 LTTngTreeNode traceStateManagerNode
;
175 // StateStacksHandler
176 for (ITmfTrace rtrace
: rtraces
) {
177 traceName
= rtrace
.getName();
178 traceStateManagerNode
= experimentNode
.getChildByName(traceName
);
179 // Node does not exist for this experiment, so needs to be
181 if (traceStateManagerNode
== null) {
182 traceStateManagerNode
= StateManagerFactory
.getManager(rtrace
, experimentNode
);
183 experimentNode
.addChild(traceStateManagerNode
);
187 // Reset event provider to handle requests for the new experiment
188 LttngCoreProviderFactory
.reset(experimentNode
);
190 // preserve the selected experiment
191 fSelectedExperiment
= experimentNode
;
195 private void clearExperimentNode(LTTngTreeNode experimentNode
) {
196 // Remove checkpoints
197 LTTngTreeNode
[] traceNodes
= experimentNode
.getChildren();
199 for (LTTngTreeNode traceStateManagerNode
: traceNodes
) {
200 IStateTraceManager traceManager
= null;
202 traceManager
= (IStateTraceManager
) traceStateManagerNode
;
203 // Clear all previously created check points as preparation to
205 traceManager
.clearCheckPoints();
206 experimentNode
.removeChild(traceStateManagerNode
);
207 } catch (ClassCastException e
) {
211 // rebuild the experiment nodes from scratch
212 removeChild(experimentNode
);
219 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentSelected(java.lang.Object,
220 * org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
223 public void experimentSelected(Object source
, TmfExperiment
<LttngEvent
> experiment
) {
225 if (experiment
== null) {
226 TraceDebug
.debug("Received experiment is null"); //$NON-NLS-1$
230 // If previous request is ongoing, cancel it before requesting a new
232 if (fStateCheckPointRequest
!= null && !fStateCheckPointRequest
.isCompleted()) {
233 fStateCheckPointRequest
.cancel();
236 synchronized (fCheckPointUpdateSyncObj
) {
237 fCheckPointUpdateBusy
= false;
238 fCheckPointUpdatePending
= false;
239 fCheckPointUpdateIndex
= 0;
248 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentUpdated
249 * (org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal, boolean)
251 @SuppressWarnings("unchecked")
253 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
254 TmfExperiment
<LttngEvent
> experiment
= (TmfExperiment
<LttngEvent
>) signal
.getExperiment();
256 if (experiment
!= fSelectedExperiment
.getValue()) {
260 synchronized (fCheckPointUpdateSyncObj
) {
261 if (fCheckPointUpdateBusy
) {
262 fCheckPointUpdatePending
= true;
263 fCheckPointUpdateRange
= signal
.getRange();
266 fCheckPointUpdateBusy
= true;
270 // If previous request is ongoing, cancel it before requesting a new
272 if (fStateCheckPointRequest
!= null && !fStateCheckPointRequest
.isCompleted()) {
273 fStateCheckPointRequest
.cancel();
276 // trigger data request to build the state system check points
277 fStateCheckPointRequest
= buildCheckPoints(experiment
, signal
.getRange(), fInitial
);
280 if (fStateCheckPointRequest
== null) {
281 synchronized (fCheckPointUpdateSyncObj
) {
282 fCheckPointUpdateBusy
= false;
288 * @return the SelectedExperiment tree node
291 public LTTngTreeNode
getSelectedExperiment() {
292 return fSelectedExperiment
;
298 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#getExperimentTimeRange()
301 @SuppressWarnings("unchecked")
302 public TmfTimeRange
getExperimentTimeRange() {
303 TmfTimeRange timeRangeResult
= null;
304 if (fSelectedExperiment
!= null) {
305 timeRangeResult
= ((TmfExperiment
<LttngEvent
>) fSelectedExperiment
.getValue()).getTimeRange();
307 return timeRangeResult
;
313 * @see java.lang.Object#finalize()
316 protected void finalize() {
317 fexperimentListener
.dispose();
323 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #waitForComplete(boolean)
326 public void waitForCompletion(boolean wait
) {
327 fwaitForCompletion
= wait
;
330 private ITmfDataRequest
<LttngEvent
> buildCheckPoints(final TmfExperiment
<LttngEvent
> experiment
,
331 final TmfTimeRange range
, boolean initial
) {
333 if (experiment
== null) {
334 TraceDebug
.debug("Received experiment is null"); //$NON-NLS-1$
338 LTTngTreeNode experimentNode
= getChildByName(experiment
.getName());
339 if (experimentNode
== null) {
340 TraceDebug
.debug("Experiment Node " + experiment
.getName() + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
344 final boolean waitForCompletion
= fwaitForCompletion
;
346 // get the trace manager nodes associated to the experiment
347 LTTngTreeNode
[] traceNodes
= experimentNode
.getChildren();
350 synchronized (this) {
351 ftraceToManagerMap
.clear();
355 for (LTTngTreeNode traceStateManagerNode
: traceNodes
) {
356 IStateTraceManager traceManager
;
358 traceManager
= (IStateTraceManager
) traceStateManagerNode
;
359 } catch (ClassCastException e
) {
360 System
.out
.println(e
.getStackTrace().toString());
364 // Clear all previously created check points as preparation to
366 traceManager
.clearCheckPoints();
368 // build the trace to manager mapping for event dispatching
369 trace
= traceManager
.getTrace();
370 synchronized (this) {
371 ftraceToManagerMap
.put(trace
, new StateTraceHelper(traceManager
));
376 // if no trace mapping
377 if (ftraceToManagerMap
.size() < 1) {
378 TraceDebug
.debug("No traces associated to experiment " + experiment
.getName()); //$NON-NLS-1$
382 fCheckPointNbEventsHandled
= 0;
384 // Prepare event data request to build state model
385 ITmfEventRequest
<LttngEvent
> request
= new TmfEventRequest
<LttngEvent
>(LttngEvent
.class, range
,
386 fCheckPointUpdateIndex
, TmfEventRequest
.ALL_DATA
, LttngConstants
.DEFAULT_BLOCK_SIZE
,
387 ITmfDataRequest
.ExecutionType
.BACKGROUND
) {
392 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData()
395 public void handleData(LttngEvent event
) {
396 super.handleData(event
);
398 // Tracer.trace("Chk: " + event.getTimestamp());
399 fCheckPointNbEventsHandled
++;
400 ITmfTrace trace
= event
.getParentTrace();
402 StateTraceHelper helper
= ftraceToManagerMap
.get(trace
);
404 if (helper
!= null) {
405 helper
.incrementNumberRead();
407 // obtain synthetic event
408 LttngSyntheticEvent synEvent
= updateSynEvent(event
, helper
.getTraceModel());
410 // update state system, and save check points as needed
411 helper
.getStateManager().handleEvent(synEvent
, helper
.getNumberRead());
413 TraceDebug
.debug("StateTraceManager not found for trace" //$NON-NLS-1$
422 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted()
425 public void handleCompleted() {
426 super.handleCompleted();
427 printCompletedMessage();
429 if (!waitForCompletion
) {
430 synchronized (fCheckPointUpdateSyncObj
) {
431 fCheckPointUpdateBusy
= false;
432 fCheckPointUpdateIndex
+= fCheckPointNbEventsHandled
;
433 if (fCheckPointUpdatePending
) {
434 fCheckPointUpdatePending
= false;
435 fCheckPointUpdateBusy
= true;
436 buildCheckPoints(experiment
, fCheckPointUpdateRange
, false);
447 private void printCompletedMessage() {
448 if (TraceDebug
.isDEBUG()) {
450 .debug("Trace check point building completed, number of events handled: " + fCheckPointNbEventsHandled
+ "\n\t\t"); //$NON-NLS-1$ //$NON-NLS-2$
451 for (StateTraceHelper helper
: ftraceToManagerMap
.values()) {
452 TraceDebug
.debug(helper
.getStateManager().toString() + "\n\t\t"); //$NON-NLS-1$
458 // Execute event data request
459 experiment
.sendRequest(request
);
461 if (waitForCompletion
) {
463 request
.waitForCompletion();
464 synchronized (fCheckPointUpdateSyncObj
) {
465 fCheckPointUpdateBusy
= false;
466 fCheckPointUpdateIndex
+= fCheckPointNbEventsHandled
;
467 if (fCheckPointUpdatePending
) {
468 fCheckPointUpdatePending
= false;
469 fCheckPointUpdateBusy
= true;
470 buildCheckPoints(experiment
, fCheckPointUpdateRange
, false);
473 } catch (InterruptedException e
) {
481 private LttngSyntheticEvent
updateSynEvent(LttngEvent e
, LttngTraceState stateModel
) {
482 if (syntheticEvent
== null || syntheticEvent
.getBaseEvent() != e
) {
483 syntheticEvent
= new LttngSyntheticEvent(e
);
486 // Trace model needed by application handlers
487 syntheticEvent
.setTraceModel(stateModel
);
488 syntheticEvent
.setSequenceInd(SequenceInd
.UPDATE
);
490 return syntheticEvent
;
494 * Helper class that wraps the StateTraceManager, the current LTTngTraceState and the number of read events
499 private class StateTraceHelper
{
501 IStateTraceManager stateTraceManager
= null;
502 long numberEventsRead
= 0;
503 LttngTraceState stateTraceModel
= null;
508 * @param stateManager
509 * The StateTraceManager the helper is for
511 public StateTraceHelper(IStateTraceManager stateManager
) {
512 this.stateTraceManager
= stateManager
;
513 // Get the TraceState at the beginning of the trace
514 this.stateTraceManager
.restoreCheckPointByTimestamp(stateManager
.getTrace().getStartTime());
515 this.stateTraceModel
= this.stateTraceManager
.getStateModel();
519 * Returns the StateTraceManager
521 * @return IStateTraceManager
523 public IStateTraceManager
getStateManager() {
524 return stateTraceManager
;
528 * Returns the number of read events
532 public long getNumberRead() {
533 return numberEventsRead
;
537 * Increments the number of read events
539 public void incrementNumberRead() {
544 * Returns the current LTTngTraceState
546 * @return LttngTraceState
548 public LttngTraceState
getTraceModel() {
549 return stateTraceModel
;