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