Rename xxx.lttng to xxx.lttng.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.core / src / org / eclipse / linuxtools / lttng / 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.lttng.state.experiment;
14
15 import java.util.HashMap;
16 import java.util.Map;
17
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;
39
40 /**
41 * @author alvaro
42 *
43 */
44 public class StateExperimentManager extends LTTngTreeNode implements ILttExperimentSelectedListener,
45 IStateExperimentManager {
46
47 // ========================================================================
48 // Data
49 // =======================================================================
50 private LTTngTreeNode fSelectedExperiment = null; // one selected experiment
51 // supported
52 private final StateExperimentListener fexperimentListener;
53 private boolean fwaitForCompletion = false;
54 /**
55 * Used to route incoming events to proper trace manager, during check point building
56 */
57 private final Map<ITmfTrace, StateTraceHelper> ftraceToManagerMap = new HashMap<ITmfTrace, StateTraceHelper>();
58
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;
68
69 // ========================================================================
70 // Constructors
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);
76 }
77
78 @TmfSignalHandler
79 @SuppressWarnings({ "unchecked", "rawtypes" })
80 public void experimentSelected(TmfExperimentSelectedSignal signal) {
81 experimentSelected_prep(signal.getExperiment());
82 }
83
84 // ========================================================================
85 // Methods
86 // =======================================================================
87
88 // /* (non-Javadoc)
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)
90 // */
91 // public ILttngSyntEventRequest readExperimentTimeWindow(TmfTimeRange trange,
92 // Object source, IRequestStatusListener listener,
93 // ITransEventProcessor processor) {
94 //
95 // ILttngSyntEventRequest request = null;
96 //
97 // // validate
98 // if (fSelectedExperiment != null) {
99 // // Get all trace manager nodes
100 // LTTngTreeNode[] traceMgrs = fSelectedExperiment.getChildren();
101 //
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,
108 // listener,
109 // processor);
110 // }
111 // }
112 // } else {
113 // if (fSelectedExperiment == null) {
114 // TraceDebug.debug("No experiment selected");
115 // }
116 // }
117 //
118 // return request;
119 // }
120
121 // /* (non-Javadoc)
122 // * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#readExperiment(java.lang.String, org.eclipse.linuxtools.lttng.state.IStateDataRequestListener)
123 // */
124 // @SuppressWarnings("unchecked")
125 // public void readExperiment(Object source, IRequestStatusListener listener,
126 // ITransEventProcessor processor) {
127 // // validate
128 // if (fSelectedExperiment != null) {
129 // TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fSelectedExperiment
130 // .getValue();
131 // TmfTimeRange trange = experiment.getTimeRange();
132 // readExperimentTimeWindow(trange, source, listener, processor);
133 // } else {
134 // TraceDebug.debug("No selected experiment available");
135 // }
136 // }
137
138 /*
139 * (non-Javadoc)
140 *
141 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #experimentSelected_prep
142 * (org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
143 */
144 @Override
145 public void experimentSelected_prep(TmfExperiment<LttngEvent> experiment) {
146
147 if (fSelectedExperiment != null) {
148 clearExperimentNode(fSelectedExperiment);
149 fSelectedExperiment = null;
150 }
151
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;
159 }
160
161 // Make sure all traces involved have a corresponding state manager
162 // and
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);
169 }
170
171 // Make sure the traces exists in the tree
172 ITmfTrace[] rtraces = experiment.getTraces();
173 String traceName;
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
180 // created
181 if (traceStateManagerNode == null) {
182 traceStateManagerNode = StateManagerFactory.getManager(rtrace, experimentNode);
183 experimentNode.addChild(traceStateManagerNode);
184 }
185 }
186
187 // Reset event provider to handle requests for the new experiment
188 LttngCoreProviderFactory.reset(experimentNode);
189
190 // preserve the selected experiment
191 fSelectedExperiment = experimentNode;
192 }
193 }
194
195 private void clearExperimentNode(LTTngTreeNode experimentNode) {
196 // Remove checkpoints
197 LTTngTreeNode[] traceNodes = experimentNode.getChildren();
198
199 for (LTTngTreeNode traceStateManagerNode : traceNodes) {
200 IStateTraceManager traceManager = null;
201 try {
202 traceManager = (IStateTraceManager) traceStateManagerNode;
203 // Clear all previously created check points as preparation to
204 // re-build
205 traceManager.clearCheckPoints();
206 experimentNode.removeChild(traceStateManagerNode);
207 } catch (ClassCastException e) {
208 // Nothing to do
209 }
210
211 // rebuild the experiment nodes from scratch
212 removeChild(experimentNode);
213 }
214 }
215
216 /*
217 * (non-Javadoc)
218 *
219 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentSelected(java.lang.Object,
220 * org.eclipse.linuxtools.tmf.experiment.TmfExperiment)
221 */
222 @Override
223 public void experimentSelected(Object source, TmfExperiment<LttngEvent> experiment) {
224 // validate
225 if (experiment == null) {
226 TraceDebug.debug("Received experiment is null"); //$NON-NLS-1$
227 return;
228 }
229
230 // If previous request is ongoing, cancel it before requesting a new
231 // one.
232 if (fStateCheckPointRequest != null && !fStateCheckPointRequest.isCompleted()) {
233 fStateCheckPointRequest.cancel();
234 }
235
236 synchronized (fCheckPointUpdateSyncObj) {
237 fCheckPointUpdateBusy = false;
238 fCheckPointUpdatePending = false;
239 fCheckPointUpdateIndex = 0;
240 }
241
242 fInitial = true;
243 }
244
245 /*
246 * (non-Javadoc)
247 *
248 * @see org.eclipse.linuxtools.lttng.signal.ILttExperimentSelectedListener# experimentUpdated
249 * (org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal, boolean)
250 */
251 @SuppressWarnings("unchecked")
252 @Override
253 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
254 TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) signal.getExperiment();
255 // validate
256 if (experiment != fSelectedExperiment.getValue()) {
257 return;
258 }
259
260 synchronized (fCheckPointUpdateSyncObj) {
261 if (fCheckPointUpdateBusy) {
262 fCheckPointUpdatePending = true;
263 fCheckPointUpdateRange = signal.getRange();
264 return;
265 } else {
266 fCheckPointUpdateBusy = true;
267 }
268 }
269
270 // If previous request is ongoing, cancel it before requesting a new
271 // one.
272 if (fStateCheckPointRequest != null && !fStateCheckPointRequest.isCompleted()) {
273 fStateCheckPointRequest.cancel();
274 }
275
276 // trigger data request to build the state system check points
277 fStateCheckPointRequest = buildCheckPoints(experiment, signal.getRange(), fInitial);
278 fInitial = false;
279
280 if (fStateCheckPointRequest == null) {
281 synchronized (fCheckPointUpdateSyncObj) {
282 fCheckPointUpdateBusy = false;
283 }
284 }
285 }
286
287 /**
288 * @return the SelectedExperiment tree node
289 */
290 @Override
291 public LTTngTreeNode getSelectedExperiment() {
292 return fSelectedExperiment;
293 }
294
295 /*
296 * (non-Javadoc)
297 *
298 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager#getExperimentTimeRange()
299 */
300 @Override
301 @SuppressWarnings("unchecked")
302 public TmfTimeRange getExperimentTimeRange() {
303 TmfTimeRange timeRangeResult = null;
304 if (fSelectedExperiment != null) {
305 timeRangeResult = ((TmfExperiment<LttngEvent>) fSelectedExperiment.getValue()).getTimeRange();
306 }
307 return timeRangeResult;
308 }
309
310 /*
311 * (non-Javadoc)
312 *
313 * @see java.lang.Object#finalize()
314 */
315 @Override
316 protected void finalize() {
317 fexperimentListener.dispose();
318 }
319
320 /*
321 * (non-Javadoc)
322 *
323 * @see org.eclipse.linuxtools.lttng.state.experiment.IStateExperimentManager #waitForComplete(boolean)
324 */
325 @Override
326 public void waitForCompletion(boolean wait) {
327 fwaitForCompletion = wait;
328 }
329
330 private ITmfDataRequest<LttngEvent> buildCheckPoints(final TmfExperiment<LttngEvent> experiment,
331 final TmfTimeRange range, boolean initial) {
332 // validate
333 if (experiment == null) {
334 TraceDebug.debug("Received experiment is null"); //$NON-NLS-1$
335 return null;
336 }
337
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$
341 return null;
342 }
343
344 final boolean waitForCompletion = fwaitForCompletion;
345
346 // get the trace manager nodes associated to the experiment
347 LTTngTreeNode[] traceNodes = experimentNode.getChildren();
348
349 if (initial) {
350 synchronized (this) {
351 ftraceToManagerMap.clear();
352 }
353
354 ITmfTrace trace;
355 for (LTTngTreeNode traceStateManagerNode : traceNodes) {
356 IStateTraceManager traceManager;
357 try {
358 traceManager = (IStateTraceManager) traceStateManagerNode;
359 } catch (ClassCastException e) {
360 System.out.println(e.getStackTrace().toString());
361 return null;
362 }
363
364 // Clear all previously created check points as preparation to
365 // re-build
366 traceManager.clearCheckPoints();
367
368 // build the trace to manager mapping for event dispatching
369 trace = traceManager.getTrace();
370 synchronized (this) {
371 ftraceToManagerMap.put(trace, new StateTraceHelper(traceManager));
372 }
373 }
374 }
375
376 // if no trace mapping
377 if (ftraceToManagerMap.size() < 1) {
378 TraceDebug.debug("No traces associated to experiment " + experiment.getName()); //$NON-NLS-1$
379 return null;
380 }
381
382 fCheckPointNbEventsHandled = 0;
383
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) {
388
389 /*
390 * (non-Javadoc)
391 *
392 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData()
393 */
394 @Override
395 public void handleData(LttngEvent event) {
396 super.handleData(event);
397 if (event != null) {
398 // Tracer.trace("Chk: " + event.getTimestamp());
399 fCheckPointNbEventsHandled++;
400 ITmfTrace trace = event.getParentTrace();
401
402 StateTraceHelper helper = ftraceToManagerMap.get(trace);
403
404 if (helper != null) {
405 helper.incrementNumberRead();
406
407 // obtain synthetic event
408 LttngSyntheticEvent synEvent = updateSynEvent(event, helper.getTraceModel());
409
410 // update state system, and save check points as needed
411 helper.getStateManager().handleEvent(synEvent, helper.getNumberRead());
412 } else {
413 TraceDebug.debug("StateTraceManager not found for trace" //$NON-NLS-1$
414 + trace.getName());
415 }
416 }
417 }
418
419 /*
420 * (non-Javadoc)
421 *
422 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted()
423 */
424 @Override
425 public void handleCompleted() {
426 super.handleCompleted();
427 printCompletedMessage();
428
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);
437 }
438 }
439 }
440 }
441
442 /*
443 * /**
444 *
445 * @param header
446 */
447 private void printCompletedMessage() {
448 if (TraceDebug.isDEBUG()) {
449 TraceDebug
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$
453 }
454 }
455 }
456 };
457
458 // Execute event data request
459 experiment.sendRequest(request);
460
461 if (waitForCompletion) {
462 try {
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);
471 }
472 }
473 } catch (InterruptedException e) {
474 e.printStackTrace();
475 }
476 }
477
478 return request;
479 }
480
481 private LttngSyntheticEvent updateSynEvent(LttngEvent e, LttngTraceState stateModel) {
482 if (syntheticEvent == null || syntheticEvent.getBaseEvent() != e) {
483 syntheticEvent = new LttngSyntheticEvent(e);
484 }
485
486 // Trace model needed by application handlers
487 syntheticEvent.setTraceModel(stateModel);
488 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
489
490 return syntheticEvent;
491 }
492
493 /**
494 * Helper class that wraps the StateTraceManager, the current LTTngTraceState and the number of read events
495 *
496 * @author bHufmann
497 *
498 */
499 private class StateTraceHelper {
500
501 IStateTraceManager stateTraceManager = null;
502 long numberEventsRead = 0;
503 LttngTraceState stateTraceModel = null;
504
505 /**
506 * Constructor
507 *
508 * @param stateManager
509 * The StateTraceManager the helper is for
510 */
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();
516 }
517
518 /**
519 * Returns the StateTraceManager
520 *
521 * @return IStateTraceManager
522 */
523 public IStateTraceManager getStateManager() {
524 return stateTraceManager;
525 }
526
527 /**
528 * Returns the number of read events
529 *
530 * @return long
531 */
532 public long getNumberRead() {
533 return numberEventsRead;
534 }
535
536 /**
537 * Increments the number of read events
538 */
539 public void incrementNumberRead() {
540 ++numberEventsRead;
541 }
542
543 /**
544 * Returns the current LTTngTraceState
545 *
546 * @return LttngTraceState
547 */
548 public LttngTraceState getTraceModel() {
549 return stateTraceModel;
550 }
551 }
552 }
This page took 0.043837 seconds and 5 git commands to generate.