2010-11-10 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug315307
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng / src / org / eclipse / linuxtools / lttng / control / LttngSyntheticEventProvider.java
CommitLineData
5d10d135
ASL
1/*******************************************************************************
2 * Copyright (c) 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
3f2b9283 11 * Marc Dumais (marc.dumais@ericsson.com) - Fix for 316455 (first part)
5d10d135
ASL
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.lttng.control;
15
16import java.util.HashMap;
3f2b9283
FC
17import java.util.Iterator;
18import java.util.List;
5d10d135 19import java.util.Map;
3f2b9283 20import java.util.Vector;
5d10d135
ASL
21
22import org.eclipse.linuxtools.lttng.TraceDebug;
23import org.eclipse.linuxtools.lttng.event.LttngEvent;
24import org.eclipse.linuxtools.lttng.event.LttngEventType;
25import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent;
26import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd;
27import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
28import org.eclipse.linuxtools.lttng.model.LTTngTreeNode;
29import org.eclipse.linuxtools.lttng.request.LttngBaseEventRequest;
30import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
31import org.eclipse.linuxtools.lttng.state.evProcessor.state.StateEventToHandlerFactory;
32import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
33import org.eclipse.linuxtools.lttng.state.trace.IStateTraceManager;
34import org.eclipse.linuxtools.tmf.component.TmfEventProvider;
35import org.eclipse.linuxtools.tmf.event.TmfEventSource;
36import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
37import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
38import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
39import org.eclipse.linuxtools.tmf.request.ITmfDataRequest;
40import org.eclipse.linuxtools.tmf.request.ITmfEventRequest;
5d10d135 41import org.eclipse.linuxtools.tmf.request.TmfEventRequest;
9b635e61
FC
42import org.eclipse.linuxtools.tmf.signal.TmfEndSynchSignal;
43import org.eclipse.linuxtools.tmf.signal.TmfStartSynchSignal;
5d10d135 44import org.eclipse.linuxtools.tmf.trace.ITmfContext;
9b635e61 45import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
5d10d135
ASL
46import org.eclipse.linuxtools.tmf.trace.TmfContext;
47import org.eclipse.linuxtools.tmf.trace.TmfTrace;
48
49/**
50 * @author alvaro
51 *
52 */
a72a38d9 53public class LttngSyntheticEventProvider extends TmfEventProvider<LttngSyntheticEvent> {
5d10d135
ASL
54
55 // ========================================================================
56 // Data
57 // ========================================================================
58 public static final int BLOCK_SIZE = 1;
3d62f8b7 59 public static final int NB_EVENTS = 1;
f9673903 60 public static final int QUEUE_SIZE = 1; // lttng specific, one event at a time
5d10d135 61
5d10d135 62 private ITmfDataRequest<LttngSyntheticEvent> fmainRequest = null;
c1c69938
FC
63 private LttngBaseEventRequest fSubRequest = null;
64
3f2b9283
FC
65 private final List<IStateTraceManager> fEventProviderRequests = new Vector<IStateTraceManager>();
66
5d10d135 67 private final LttngSyntheticEvent fStatusEvent;
5d10d135
ASL
68 volatile boolean startIndSent = false;
69 private LTTngTreeNode fExperiment = null;
3f2b9283 70 private ITransEventProcessor fstateUpdateProcessor = StateEventToHandlerFactory.getInstance();
5d10d135 71 private boolean waitForRequest = false;
3f2b9283
FC
72 long dispatchTime = 0L;
73 private final Map<ITmfTrace, LttngTraceState> traceToTraceStateModel = new HashMap<ITmfTrace, LttngTraceState>();
5d10d135 74
c1c69938
FC
75 private boolean fIsExperimentNotified = false;
76
5d10d135
ASL
77 // ========================================================================
78 // Constructor
79 // ========================================================================
80 /**
81 * Accessibility to package - use factory instead of this constructor
82 *
83 * @param type
84 */
85 LttngSyntheticEventProvider(Class<LttngSyntheticEvent> type) {
9c4eb5f7 86 super("LttngSyntheticEventProvider", type, QUEUE_SIZE); //$NON-NLS-1$
5d10d135
ASL
87
88 // prepare empty instance status indicators and allow them to travel via
89 // the framework
90 TmfEventSource source = new TmfEventSource(this);
91 LttngEventType dtype = new LttngEventType();
f9673903
FC
92 LttngTimestamp statusTimeStamp = new LttngTimestamp(
93 TmfTimestamp.Zero);
5d10d135 94
f9673903
FC
95 fStatusEvent = new LttngSyntheticEvent(null, statusTimeStamp, source,
96 dtype, null, null, null);
5d10d135 97 fStatusEvent.setSequenceInd(SequenceInd.STARTREQ);
5d10d135
ASL
98 }
99
100 // ========================================================================
101 // Methods
102 // ========================================================================
550d787e 103
5d10d135
ASL
104 @SuppressWarnings("unchecked")
105 @Override
3f2b9283 106 public ITmfContext armRequest(final ITmfDataRequest<LttngSyntheticEvent> request) {
5d10d135
ASL
107 // validate
108 // make sure we have the right type of request
109 if (!(request instanceof ITmfEventRequest<?>)) {
110 request.cancel();
9c4eb5f7 111 TraceDebug.debug("Request is not an instance of ITmfEventRequest"); //$NON-NLS-1$
5d10d135
ASL
112 return null;
113 }
114
115 if (fExperiment == null) {
9c4eb5f7 116 TraceDebug.debug("Experiment is null"); //$NON-NLS-1$
5d10d135
ASL
117 request.cancel();
118 return null;
119 }
120
121 // get ready to start processing
122 reset(fExperiment);
123
124 // At least one base provider shall be available
550d787e 125 if (fEventProviderRequests.size() < 1) {
5d10d135 126 request.cancel();
9c4eb5f7 127 TraceDebug.debug("No Base event providers available"); //$NON-NLS-1$
5d10d135
ASL
128 return null;
129 }
130
131 fmainRequest = request;
c1c69938 132
5d10d135
ASL
133 // define event data handling
134 ITmfEventRequest<LttngSyntheticEvent> eventRequest = (ITmfEventRequest<LttngSyntheticEvent>) fmainRequest;
135 TmfTimeRange reqWindow = eventRequest.getRange();
550d787e 136
9c4eb5f7 137 TraceDebug.debug("Main Synthethic event request started on thread: " + Thread.currentThread().getName()); //$NON-NLS-1$
5d10d135 138
9b635e61
FC
139 TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fExperiment.getValue();
140 experiment.startSynch(new TmfStartSynchSignal(0));
3f2b9283
FC
141
142 TmfTimeRange adjustedRange = reqWindow;
143
144 // Figure-out if we need to increase the range of the request: if some
145 // checkpoints are before the beginning of the range, increase the
146 // range to catch them. We will then exercise the state system of
147 // those traces until the requested beginning time range, discarding
148 // the unrequested data.
149 IStateTraceManager traceManager;
150 Iterator<IStateTraceManager> iter = fEventProviderRequests.iterator();
151 // For each traceManager in the current experiment...
152 while(iter.hasNext()) {
153 traceManager = iter.next();
5d10d135 154 // restore trace state system to nearest check point
f9673903
FC
155 TmfTimestamp checkPoint = traceManager
156 .restoreCheckPointByTimestamp(reqWindow.getStartTime());
550d787e 157
3f2b9283
FC
158 // validate that the checkpoint restored is within requested bounds
159 // (not outside the current trace's range or after the end of requested range)
5d10d135 160 TmfTimeRange traceRange = traceManager.getTrace().getTimeRange();
550d787e
FC
161 if ((checkPoint != null) && !(
162 checkPoint.getValue() >= traceRange.getStartTime().getValue() &&
163 checkPoint.getValue() <= traceRange.getEndTime().getValue() &&
164 checkPoint.getValue() < reqWindow.getEndTime().getValue())
165 ) {
3f2b9283
FC
166 // checkpoint is out of trace bounds; no need to adjust request for this
167 // trace
168 }
169 else {
170 // use checkpoint time as new startTime for request if it's earlier than
171 // current startTime
172 if (checkPoint != null && adjustedRange.getStartTime().getValue() > checkPoint.getValue()) {
173 adjustedRange = new TmfTimeRange(checkPoint, reqWindow.getEndTime());
174 }
175 }
176 // Save which trace state model corresponds to current trace
177 traceToTraceStateModel.put(traceManager.getTrace(), traceManager.getStateModel());
178 }
c1c69938 179
3f2b9283 180 dispatchTime = reqWindow.getStartTime().getValue();
c1c69938 181
3f2b9283 182 // Create a single request for all traces in the experiment, with coalesced time range.
c1c69938
FC
183 fSubRequest = new LttngBaseEventRequest(adjustedRange, reqWindow.getStartTime(),
184 0, TmfEventRequest.ALL_DATA, BLOCK_SIZE, eventRequest.getExecType() /*ITmfDataRequest.ExecutionType.FOREGROUND*/) {
3f2b9283
FC
185
186 private LttngSyntheticEvent syntheticEvent = null;
3f2b9283
FC
187
188 /*
189 * (non-Javadoc)
190 *
191 * @see org.eclipse.linuxtools.lttng.control.LttngEventRequest#handleData()
192 */
193 @Override
194 public void handleData(LttngEvent event) {
195 super.handleData(event);
196 if (event != null) {
c1c69938
FC
197 synchronized (LttngSyntheticEventProvider.this) {
198 // Check if request was canceled
199 if ((fmainRequest == null) || (fmainRequest.isCompleted()) ) {
9c4eb5f7 200 TraceDebug.debug("fmainRequest was canceled. Ignoring event " + event); //$NON-NLS-1$
c1c69938
FC
201 return;
202 }
203
204 handleIncomingData(event);
205 }
3f2b9283 206 } else {
9c4eb5f7 207 TraceDebug.debug("handle data received with no data"); //$NON-NLS-1$
3f2b9283 208 }
5d10d135 209 }
3f2b9283
FC
210
211 /*
212 * (non-Javadoc)
213 *
c1c69938 214 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted()
3f2b9283
FC
215 */
216 @Override
c1c69938 217 public void handleCompleted() {
3f2b9283 218 // mark this sub-request as completed
c1c69938
FC
219 handleProviderDone(!isCancelled() && !isFailed());
220 super.handleCompleted();
550d787e 221 }
5d10d135 222
3f2b9283
FC
223 /**
224 * Trigger the Analysis and sequential control of the events.
225 *
226 * @param e
227 */
228 private void handleIncomingData(LttngEvent e) {
229 long eventTime = e.getTimestamp().getValue();
230
231 TmfTrace<LttngEvent> inTrace = e.getParentTrace();
232 LttngTraceState traceModel = traceToTraceStateModel.get(inTrace);
233
c1c69938 234 // queue the new event data
3f2b9283
FC
235 updateSynEvent(e);
236
237 // If time at or above requested time, update application
238 if (eventTime >= dispatchTime) {
239 // Before update
240 syntheticEvent.setSequenceInd(SequenceInd.BEFORE);
241 fmainRequest.handleData(syntheticEvent);
3f2b9283
FC
242
243 // Update state locally
244 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
245 fstateUpdateProcessor.process(syntheticEvent, traceModel);
246
247 // After Update
248 syntheticEvent.setSequenceInd(SequenceInd.AFTER);
249 fmainRequest.handleData(syntheticEvent);
3f2b9283 250
3f2b9283
FC
251 } else {
252 // event time is between checkpoint adjusted time and
253 // requested time i.e. application does not expect the
254 // event, however the state system needs to be re-built
255 // to the dispatch point
256 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
257 fstateUpdateProcessor.process(syntheticEvent, traceModel);
5d10d135 258 }
3f2b9283
FC
259 }
260
261 /**
262 * Create a synthetic event from the received new reference, if
263 * the reference is the same there is no need for a new instance
264 *
265 * if this is the first event for this request, call start
266 * handler
267 *
268 * @param e
269 * @return
270 */
271 private LttngSyntheticEvent updateSynEvent(LttngEvent e) {
c1c69938 272 if ((syntheticEvent == null) || (syntheticEvent.getBaseEvent() != e)) {
3f2b9283 273 syntheticEvent = new LttngSyntheticEvent(e);
5d10d135 274 }
3f2b9283
FC
275
276 TmfTrace<LttngEvent> inTrace = e.getParentTrace();
277 LttngTraceState traceModel = traceToTraceStateModel.get(inTrace);
f9673903 278
3f2b9283
FC
279 // Trace model needed by application handlers
280 syntheticEvent.setTraceModel(traceModel);
281
282 // send the start request indication once per request thread
283 if (!startIndSent) {
9c4eb5f7 284 TraceDebug.debug("Thread started: " + Thread.currentThread().getName()); //$NON-NLS-1$
3f2b9283
FC
285 handleProviderStarted(traceModel);
286 startIndSent = true;
5d10d135
ASL
287 }
288
3f2b9283
FC
289 return syntheticEvent;
290 }
291 };
292
293 // start request
294 TmfExperiment<LttngEvent> provider = (TmfExperiment<LttngEvent>) fExperiment.getValue();
c1c69938 295 provider.sendRequest(fSubRequest);
3f2b9283 296
c1c69938
FC
297 // notify LTTngEvent provider that all requests were sent
298 synchronized (this) {
299 TmfExperiment.getCurrentExperiment().notifyPendingRequest(false);
300 fIsExperimentNotified = false;
301 }
5d10d135 302
9b635e61
FC
303 experiment.endSynch(new TmfEndSynchSignal(0));
304
5d10d135 305 // Return a dummy context, not used for relay provider
c1c69938 306 return new TmfContext();
5d10d135
ASL
307 }
308
309 /**
310 * Notify listeners to prepare to receive data e.g. clean previous data etc.
311 */
c1c69938 312 public synchronized void handleProviderStarted(LttngTraceState traceModel) {
3d62f8b7 313 LttngSyntheticEvent startIndEvent = new LttngSyntheticEvent(fStatusEvent);
5d10d135
ASL
314 startIndEvent.setSequenceInd(SequenceInd.STARTREQ);
315
316 // Notify application
f9673903 317 fmainRequest.handleData(startIndEvent);
5d10d135
ASL
318
319 // Notify state event processor
320 fstateUpdateProcessor.process(startIndEvent, null);
321 }
322
323 /**
f9673903
FC
324 * Notify listeners, no more events for the current request will be
325 * distributed e.g. update view.
5d10d135 326 */
c1c69938 327 public synchronized void handleProviderDone(boolean isSuccess) {
3f2b9283
FC
328 // Notify application. One notification per trace so the last state of each trace can be
329 // drawn
c1c69938
FC
330 for (LttngTraceState traceModel : traceToTraceStateModel.values()) {
331 // Take the trace model from traceToTraceStateModel list since it has a copy
332 // of the state
333 LttngSyntheticEvent finishEvent = new LttngSyntheticEvent(fStatusEvent);
334 finishEvent.setSequenceInd(SequenceInd.ENDREQ);
335 finishEvent.setTraceModel(traceModel);
336
337 fmainRequest.handleData(finishEvent);
338 }
339
340 if(isSuccess) {
341 // Finish main request
342 fmainRequest.done();
343 }
344 else {
345 // Cancel main request
346 fmainRequest.cancel();
347
348 }
5d10d135
ASL
349 }
350
351 /**
352 * Reset provider to a state ready to begin thread execution
353 *
354 * @param experimentNode
355 */
550d787e 356 public synchronized void reset(LTTngTreeNode experimentNode) {
c1c69938
FC
357
358 conditionallyCancelRequests();
5d10d135 359
550d787e 360 fEventProviderRequests.clear();
5d10d135
ASL
361 startIndSent = false;
362
363 // set of base event providers
364 if (fExperiment != null) {
365 LTTngTreeNode[] traces = fExperiment.getChildren();
366 for (LTTngTreeNode trace : traces) {
367 IStateTraceManager traceBaseEventProvider = (IStateTraceManager) trace;
3f2b9283 368 fEventProviderRequests.add(traceBaseEventProvider);
5d10d135
ASL
369 }
370 }
371
372 if (fExperiment != experimentNode) {
373 updateExperimentNode(experimentNode);
374 }
375 }
376
377 /**
378 * Point to a new experiment reference
379 *
380 * @param experiment
381 */
382 private synchronized void updateExperimentNode(LTTngTreeNode experiment) {
f9673903
FC
383 if (experiment != null
384 && experiment.getValue() instanceof TmfExperiment<?>) {
5d10d135
ASL
385 fExperiment = experiment;
386 } else {
387 TraceDebug
9c4eb5f7 388 .debug("Experiment received is not instance of TmfExperiment: " //$NON-NLS-1$
f9673903 389 + experiment.getClass().getName());
5d10d135
ASL
390 }
391 }
392
393 /*
394 * (non-Javadoc)
395 *
f9673903
FC
396 * @see
397 * org.eclipse.linuxtools.tmf.component.TmfDataProvider#sendRequest(org.
5d10d135
ASL
398 * eclipse.linuxtools.tmf.request.TmfDataRequest)
399 */
cb866e08 400 @Override
550d787e 401 public void sendRequest(final ITmfDataRequest<LttngSyntheticEvent> request) {
c1c69938
FC
402 synchronized (this) {
403 if (!fIsExperimentNotified) {
404 @SuppressWarnings("unchecked")
405 TmfExperiment<LttngSyntheticEvent> experiment = (TmfExperiment<LttngSyntheticEvent>) TmfExperiment.getCurrentExperiment();
406 if (experiment != null) {
407 experiment.notifyPendingRequest(true);
408 fIsExperimentNotified = true;
409 }
410 }
411 }
412
5d10d135
ASL
413 super.sendRequest(request);
414 if (waitForRequest) {
415 try {
416 request.waitForCompletion();
417 } catch (InterruptedException e) {
418 e.printStackTrace();
419 }
420 }
421 }
422
423 /**
424 * @return the waitForRequest
425 */
426 public boolean isWaitForRequest() {
427 return waitForRequest;
428 }
429
430 /**
431 * @param waitForRequest
432 * configures the provider to wait for the request completion
433 */
434 public void setWaitForRequest(boolean waitForRequest) {
435 this.waitForRequest = waitForRequest;
436 }
437
cb866e08 438 @Override
3d62f8b7
FC
439 public LttngSyntheticEvent getNext(ITmfContext context) {
440 try {
441 fmainRequest.waitForCompletion();
442 } catch (InterruptedException e) {
443 e.printStackTrace();
444 }
445 return null;
cb866e08
FC
446 }
447
c1c69938
FC
448 /**
449 * Cancels the ongoing requests for this data provider if necessary
450 */
451 public synchronized void conditionallyCancelRequests() {
452 if ((fSubRequest != null) && (!fSubRequest.isCompleted())) {
453
9c4eb5f7 454 TraceDebug.debug("Canceling synthethic event request!"); //$NON-NLS-1$
c1c69938
FC
455
456 // This will also cancel the fmainRequest
457 fSubRequest.cancel();
458 // Reset the request references
459 fSubRequest = null;
460 fmainRequest = null;
461 }
462 }
5d10d135 463}
This page took 0.052715 seconds and 5 git commands to generate.