2010-09-15 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug287563
[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
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.lttng.control;
14
15import java.util.HashMap;
16import java.util.Map;
17
18import org.eclipse.linuxtools.lttng.TraceDebug;
19import org.eclipse.linuxtools.lttng.event.LttngEvent;
20import org.eclipse.linuxtools.lttng.event.LttngEventType;
21import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent;
22import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd;
23import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
24import org.eclipse.linuxtools.lttng.model.LTTngTreeNode;
25import org.eclipse.linuxtools.lttng.request.LttngBaseEventRequest;
26import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
27import org.eclipse.linuxtools.lttng.state.evProcessor.state.StateEventToHandlerFactory;
28import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
29import org.eclipse.linuxtools.lttng.state.trace.IStateTraceManager;
30import org.eclipse.linuxtools.tmf.component.TmfEventProvider;
31import org.eclipse.linuxtools.tmf.event.TmfEventSource;
32import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
33import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
34import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
35import org.eclipse.linuxtools.tmf.request.ITmfDataRequest;
36import org.eclipse.linuxtools.tmf.request.ITmfEventRequest;
5d10d135 37import org.eclipse.linuxtools.tmf.request.TmfEventRequest;
9b635e61
FC
38import org.eclipse.linuxtools.tmf.signal.TmfEndSynchSignal;
39import org.eclipse.linuxtools.tmf.signal.TmfStartSynchSignal;
5d10d135 40import org.eclipse.linuxtools.tmf.trace.ITmfContext;
9b635e61 41import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
5d10d135
ASL
42import org.eclipse.linuxtools.tmf.trace.TmfContext;
43import org.eclipse.linuxtools.tmf.trace.TmfTrace;
44
45/**
46 * @author alvaro
47 *
48 */
a72a38d9 49public class LttngSyntheticEventProvider extends TmfEventProvider<LttngSyntheticEvent> {
5d10d135
ASL
50
51 // ========================================================================
52 // Data
53 // ========================================================================
54 public static final int BLOCK_SIZE = 1;
3d62f8b7 55 public static final int NB_EVENTS = 1;
5d10d135
ASL
56 public static final int QUEUE_SIZE = 1; // lttng specific, one event at a
57 // time
58
59 // TmfDataProvider<LttngEvent> fExtProvider = null;
60 private ITmfDataRequest<LttngSyntheticEvent> fmainRequest = null;
550d787e 61 private final Map<IStateTraceManager, LttngBaseEventRequest> fEventProviderRequests = new HashMap<IStateTraceManager, LttngBaseEventRequest>();
5d10d135
ASL
62 private final LttngSyntheticEvent fStatusEvent;
63 private final LttngSyntheticEvent fStatusEventAck;
550d787e 64 private int fMainReqEventCount = 0;
5d10d135
ASL
65 volatile boolean startIndSent = false;
66 private LTTngTreeNode fExperiment = null;
a72a38d9 67 private ITransEventProcessor fstateUpdateProcessor = StateEventToHandlerFactory.getInstance();
5d10d135
ASL
68 private boolean waitForRequest = false;
69
70 // ========================================================================
71 // Constructor
72 // ========================================================================
73 /**
74 * Accessibility to package - use factory instead of this constructor
75 *
76 * @param type
77 */
78 LttngSyntheticEventProvider(Class<LttngSyntheticEvent> type) {
79 super("LttngSyntheticEventProvider", type, QUEUE_SIZE);
80
81 // prepare empty instance status indicators and allow them to travel via
82 // the framework
83 TmfEventSource source = new TmfEventSource(this);
84 LttngEventType dtype = new LttngEventType();
a72a38d9 85 LttngTimestamp statusTimeStamp = new LttngTimestamp(TmfTimestamp.Zero);
5d10d135 86
a72a38d9 87 fStatusEvent = new LttngSyntheticEvent(null, statusTimeStamp, source, dtype, null, null, null);
5d10d135
ASL
88 fStatusEvent.setSequenceInd(SequenceInd.STARTREQ);
89
a72a38d9 90 fStatusEventAck = new LttngSyntheticEvent(null, statusTimeStamp, source, dtype, null, null, null);
5d10d135
ASL
91 fStatusEventAck.setSequenceInd(SequenceInd.ACK);
92 }
93
94 // ========================================================================
95 // Methods
96 // ========================================================================
550d787e 97
5d10d135
ASL
98 @SuppressWarnings("unchecked")
99 @Override
a72a38d9 100 public ITmfContext armRequest(final ITmfDataRequest<LttngSyntheticEvent> request) {
5d10d135
ASL
101 // validate
102 // make sure we have the right type of request
103 if (!(request instanceof ITmfEventRequest<?>)) {
104 request.cancel();
105 TraceDebug.debug("Request is not an instance of ITmfEventRequest");
106 return null;
107 }
108
109 if (fExperiment == null) {
110 TraceDebug.debug("Experiment is null");
111 request.cancel();
112 return null;
113 }
114
115 // get ready to start processing
116 reset(fExperiment);
117
118 // At least one base provider shall be available
550d787e 119 if (fEventProviderRequests.size() < 1) {
5d10d135
ASL
120 request.cancel();
121 TraceDebug.debug("No Base event providers available");
122 return null;
123 }
124
125 fmainRequest = request;
126 // define event data handling
127 ITmfEventRequest<LttngSyntheticEvent> eventRequest = (ITmfEventRequest<LttngSyntheticEvent>) fmainRequest;
128 TmfTimeRange reqWindow = eventRequest.getRange();
550d787e 129
5d10d135
ASL
130 TraceDebug.debug("Main Synthethic event request started on thread: " + Thread.currentThread().getName());
131
132 // loop for every traceManager in current experiment
550d787e 133 boolean subRequestQueued = false;
9b635e61
FC
134 TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) fExperiment.getValue();
135 experiment.startSynch(new TmfStartSynchSignal(0));
550d787e 136 for (IStateTraceManager traceManager : fEventProviderRequests.keySet()) {
5d10d135
ASL
137
138 // restore trace state system to nearest check point
a72a38d9 139 TmfTimestamp checkPoint = traceManager.restoreCheckPointByTimestamp(reqWindow.getStartTime());
550d787e
FC
140
141 // adjust start time bound to check point
142
5d10d135
ASL
143 // validate so checkpoint restore is within requested bounds
144 TmfTimeRange traceRange = traceManager.getTrace().getTimeRange();
550d787e
FC
145 if ((checkPoint != null) && !(
146 checkPoint.getValue() >= traceRange.getStartTime().getValue() &&
147 checkPoint.getValue() <= traceRange.getEndTime().getValue() &&
148 checkPoint.getValue() < reqWindow.getEndTime().getValue())
149 ) {
5d10d135
ASL
150 // checkpoint is out of trace bounds
151 continue;
152 }
550d787e
FC
153 TmfTimeRange adjustedRange = reqWindow;
154 if (checkPoint != null) {
155 adjustedRange = new TmfTimeRange(checkPoint, reqWindow.getEndTime());
156 }
5d10d135 157
736aecd5 158 LttngTraceState traceModel = traceManager.getStateModel();
9b635e61
FC
159 // String key = (traceManager.getTrace().getPath() +
160 // traceManager.getTrace().getName()).hashCode();
161 ITmfTrace trace = traceManager.getTrace();
5d10d135 162 // create sub-request for one trace within experiment
9b635e61 163 final LttngBaseEventRequest subRequest = new LttngBaseEventRequest(adjustedRange, reqWindow.getStartTime(),
f6b14ce2 164 0, TmfEventRequest.ALL_DATA, BLOCK_SIZE, traceModel, ITmfDataRequest.ExecutionType.FOREGROUND, trace) {
5d10d135
ASL
165
166 private LttngSyntheticEvent syntheticEvent = null;
167 private LttngSyntheticEvent syntheticAckIndicator = null;
168 long subEventCount = 0L;
169
170 private final long fDispatchTime = getDispatchTime().getValue();
171 private final LttngTraceState fTraceModel = getTraceModel();
a72a38d9 172 private LttngSyntheticEvent[] fresult = new LttngSyntheticEvent[1];
5d10d135
ASL
173
174 /*
175 * (non-Javadoc)
176 *
a72a38d9 177 * @see org.eclipse.linuxtools.lttng.control.LttngEventRequest#handleData ()
5d10d135
ASL
178 */
179 @Override
180 public void handleData() {
181 LttngEvent[] events = getData();
a72a38d9
ASL
182
183 // Tracer.trace("Sep: " + events[0].getTimestamp());
9b635e61 184
5d10d135 185 if (events.length > 0) {
a72a38d9 186 handleIncomingData(events[0]);
5d10d135
ASL
187 } else {
188 TraceDebug.debug("handle data received with no data");
a72a38d9
ASL
189 // handleProviderDone(getTraceModel());
190 // done();
5d10d135
ASL
191 }
192 }
193
194 /*
195 * (non-Javadoc)
196 *
197 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#done()
198 */
199 @Override
200 public void done() {
201 // mark this sub-request as completed
202 super.done();
a72a38d9
ASL
203 handleProviderDone();
204 // super.done();
5d10d135 205 }
a72a38d9 206
5d10d135
ASL
207 /**
208 * Trigger the Analysis and sequential control of the events.
209 *
210 * @param e
211 */
212 private void handleIncomingData(LttngEvent e) {
213 long eventTime = e.getTimestamp().getValue();
214
a72a38d9 215 TmfTrace<LttngEvent> inTrace = e.getParentTrace();
9b635e61 216 if (!(inTrace == getTrace())) {
a72a38d9 217 // System.out.println("Event from a different trace discarded");
9b635e61
FC
218 return;
219 }
a72a38d9 220
5d10d135
ASL
221 // queue the new event data and an ACK
222 updateSynEvent(e);
223
5d10d135 224 // If time at or above requested time, update application
3d62f8b7 225 if (eventTime >= fDispatchTime) {
a72a38d9
ASL
226 // Load synthetic event as the result data
227 fresult[0] = syntheticEvent;
3d62f8b7 228
a72a38d9
ASL
229 // BEFORE UPDATE : update to the before state-update handlers
230 syntheticEvent.setSequenceInd(SequenceInd.BEFORE);
231 // queueResult(syntheticEvent);
232 // queueResult(syntheticAckIndicator);
233 fmainRequest.setData(fresult);
3d62f8b7 234 fmainRequest.handleData();
a72a38d9
ASL
235 // result[0] = syntheticAckIndicator;
236 // fmainRequest.setData(result);
237 // fmainRequest.handleData();
3d62f8b7 238
a72a38d9 239 // STATE UPDATE: local handlers
3d62f8b7
FC
240 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
241 fstateUpdateProcessor.process(syntheticEvent, fTraceModel);
242
a72a38d9 243 // AFTER UPDATE: update to the after state-update handlers
3d62f8b7 244 syntheticEvent.setSequenceInd(SequenceInd.AFTER);
a72a38d9
ASL
245 // queueResult(syntheticEvent);
246 // queueResult(syntheticAckIndicator);
247 fmainRequest.setData(fresult);
3d62f8b7 248 fmainRequest.handleData();
a72a38d9
ASL
249 // result[0] = syntheticAckIndicator;
250 // fmainRequest.setData(result);
251 // fmainRequest.handleData();
3d62f8b7
FC
252
253 // increment once per dispatch
254 incrementSynEvenCount();
255 subEventCount++;
256 } else {
257 // event time is between checkpoint adjusted time and
258 // requested time i.e. application does not expect the
259 // event, however the state system needs to be re-built
260 // to the dispatch point
261 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
262 fstateUpdateProcessor.process(syntheticEvent, fTraceModel);
5d10d135
ASL
263 }
264 }
265
266 /**
a72a38d9
ASL
267 * Create a synthetic event from the received new reference, if the reference is the same there is no
268 * need for a new instance
5d10d135 269 *
a72a38d9 270 * if this is the first event for this request, call start handler
5d10d135
ASL
271 *
272 * @param e
273 * @return
274 */
275 private LttngSyntheticEvent updateSynEvent(LttngEvent e) {
a72a38d9 276 if (syntheticEvent == null || syntheticEvent.getBaseEvent() != e) {
5d10d135
ASL
277 syntheticEvent = new LttngSyntheticEvent(e);
278 syntheticAckIndicator = new LttngSyntheticEvent(e);
279 syntheticAckIndicator.setSequenceInd(SequenceInd.ACK);
280 }
281
282 // Trace model needed by application handlers
283 syntheticEvent.setTraceModel(fTraceModel);
284
285 // send the start request indication once per request thread
286 if (!startIndSent) {
287 TraceDebug.debug("Thread started: " + Thread.currentThread().getName());
288 handleProviderStarted(getTraceModel());
289 startIndSent = true;
290 }
291
292 return syntheticEvent;
293 }
294 };
a72a38d9 295
5d10d135
ASL
296 // preserve the associated sub request to control it e.g.
297 // cancellation
550d787e 298 fEventProviderRequests.put(traceManager, subRequest);
5d10d135
ASL
299
300 // start request
9b635e61 301 TmfExperiment<LttngEvent> provider = (TmfExperiment<LttngEvent>) fExperiment.getValue();
8827c197 302 provider.sendRequest(subRequest);
9b635e61
FC
303
304 // provider.sendRequest(subRequest, ExecutionType.LONG);
550d787e 305 subRequestQueued = true;
5d10d135
ASL
306 }
307
9b635e61
FC
308 experiment.endSynch(new TmfEndSynchSignal(0));
309
5d10d135 310 // Return a dummy context, not used for relay provider
550d787e 311 return (subRequestQueued) ? new TmfContext() : null;
5d10d135
ASL
312 }
313
314 /**
315 * Notify listeners to prepare to receive data e.g. clean previous data etc.
316 */
317 public void handleProviderStarted(LttngTraceState traceModel) {
3d62f8b7 318 LttngSyntheticEvent startIndEvent = new LttngSyntheticEvent(fStatusEvent);
5d10d135
ASL
319 startIndEvent.setSequenceInd(SequenceInd.STARTREQ);
320
321 // Notify application
3d62f8b7
FC
322 LttngSyntheticEvent[] result = new LttngSyntheticEvent[1];
323 result[0] = startIndEvent;
324 fmainRequest.setData(result);
325 fmainRequest.handleData();
a72a38d9
ASL
326 // result[0] = fStatusEventAck;
327 // fmainRequest.setData(result);
328 // fmainRequest.handleData();
329
330 // try {
331 // queueResult(startIndEvent);
332 // queueResult(fStatusEventAck);
333 // } catch (InterruptedException e) {
334 // // TODO: cancel this request
335 // e.printStackTrace();
336 // }
5d10d135
ASL
337
338 // Notify state event processor
339 fstateUpdateProcessor.process(startIndEvent, null);
340 }
341
342 /**
a72a38d9 343 * Notify listeners, no more events for the current request will be distributed e.g. update view.
5d10d135 344 */
a72a38d9 345 public synchronized void handleProviderDone() {
5d10d135
ASL
346 // TODO: The use of a thread per main request and thread per sub-request
347 // requires
348 // to make sure the proper main request is marked completed. So a
349 // relationship of sub-requests to parent needs to be established to
350 // handle completion and cancellations properly
351
352 // Close the main request when all sub-requests are marked completed
550d787e 353 for (LttngBaseEventRequest subRequest : fEventProviderRequests.values()) {
5d10d135
ASL
354 if (subRequest != null) {
355 if (!subRequest.isCompleted()) {
356 // Not ready to complete main request
357 return;
358 }
359 }
360 }
361
a72a38d9
ASL
362 // Notify application. One notification per trace so the last state of each trace can be
363 // drawn
364 LttngTraceState traceModel;
365 for (IStateTraceManager traceMgr : fEventProviderRequests.keySet()) {
366 traceModel = traceMgr.getStateModel();
367
368 LttngSyntheticEvent finishEvent = new LttngSyntheticEvent(fStatusEvent);
369 // finishEvent.setTraceModel(traceModel);
370 // finishEvent.setParentTrace((TmfTrace<LttngEvent>) traceModel.getContext().getTraceIdRef());
371 finishEvent.setSequenceInd(SequenceInd.ENDREQ);
372 finishEvent.setTraceModel(traceModel);
373
374 LttngSyntheticEvent[] result = new LttngSyntheticEvent[1];
375 // End Request indication
376 result[0] = finishEvent;
377 fmainRequest.setData(result);
378 fmainRequest.handleData();
379
380 // // End Request processed indication
381 // result[0] = fStatusEventAck;
382 // fmainRequest.setData(result);
383 // fmainRequest.handleData();
384 }
550d787e 385
a72a38d9 386 // All sub-requests are marked completed so the main request can be completed as well
3d62f8b7
FC
387 fmainRequest.done();
388
a72a38d9
ASL
389 // try {
390 // queueResult(finishEvent);
391 // queueResult(fStatusEventAck);
392 // // End the loop in the main request
393 // queueResult(LttngSyntheticEvent.NullEvent);
394 // } catch (InterruptedException e) {
395 // // System.out.println(getName() +
396 // // ":handleProviderDone() failed to queue request");
397 // // TODO: Cancel the request
398 // // e.printStackTrace();
399 // }
5d10d135
ASL
400 }
401
402 /**
403 * Increment the global event counter i.e. events from any sub requests
404 */
405 private synchronized void incrementSynEvenCount() {
550d787e 406 fMainReqEventCount++;
5d10d135
ASL
407 }
408
409 /**
410 * @return
411 */
412 public synchronized int getSynEvenCount() {
550d787e 413 return fMainReqEventCount;
5d10d135
ASL
414 }
415
416 /**
417 * Reset provider to a state ready to begin thread execution
418 *
419 * @param experimentNode
420 */
550d787e 421 public synchronized void reset(LTTngTreeNode experimentNode) {
5d10d135
ASL
422
423 fmainRequest = null;
424
425 // Make sure previous request are terminated
550d787e 426 for (LttngBaseEventRequest tmpRequest : fEventProviderRequests.values()) {
5d10d135
ASL
427 if (tmpRequest != null && !tmpRequest.isCompleted()) {
428 tmpRequest.cancel();
429 }
430 }
431
550d787e
FC
432 fEventProviderRequests.clear();
433 fMainReqEventCount = 0;
5d10d135
ASL
434 startIndSent = false;
435
436 // set of base event providers
437 if (fExperiment != null) {
438 LTTngTreeNode[] traces = fExperiment.getChildren();
439 for (LTTngTreeNode trace : traces) {
440 IStateTraceManager traceBaseEventProvider = (IStateTraceManager) trace;
550d787e 441 fEventProviderRequests.put(traceBaseEventProvider, null);
5d10d135
ASL
442 }
443 }
444
445 if (fExperiment != experimentNode) {
446 updateExperimentNode(experimentNode);
447 }
448 }
449
450 /**
451 * Point to a new experiment reference
452 *
453 * @param experiment
454 */
455 private synchronized void updateExperimentNode(LTTngTreeNode experiment) {
a72a38d9 456 if (experiment != null && experiment.getValue() instanceof TmfExperiment<?>) {
5d10d135
ASL
457 fExperiment = experiment;
458 } else {
459 TraceDebug
a72a38d9 460 .debug("Experiment received is not instance of TmfExperiment: " + experiment.getClass().getName());
5d10d135
ASL
461 }
462 }
463
464 /*
465 * (non-Javadoc)
466 *
a72a38d9 467 * @see org.eclipse.linuxtools.tmf.component.TmfDataProvider#sendRequest(org.
5d10d135
ASL
468 * eclipse.linuxtools.tmf.request.TmfDataRequest)
469 */
cb866e08 470 @Override
550d787e 471 public void sendRequest(final ITmfDataRequest<LttngSyntheticEvent> request) {
5d10d135
ASL
472 super.sendRequest(request);
473 if (waitForRequest) {
474 try {
475 request.waitForCompletion();
476 } catch (InterruptedException e) {
477 e.printStackTrace();
478 }
479 }
480 }
481
482 /**
483 * @return the waitForRequest
484 */
485 public boolean isWaitForRequest() {
486 return waitForRequest;
487 }
488
489 /**
490 * @param waitForRequest
491 * configures the provider to wait for the request completion
492 */
493 public void setWaitForRequest(boolean waitForRequest) {
494 this.waitForRequest = waitForRequest;
495 }
496
cb866e08 497 @Override
3d62f8b7
FC
498 public LttngSyntheticEvent getNext(ITmfContext context) {
499 try {
500 fmainRequest.waitForCompletion();
501 } catch (InterruptedException e) {
502 e.printStackTrace();
503 }
504 return null;
cb866e08
FC
505 }
506
a72a38d9
ASL
507 // @Override
508 // public LttngSyntheticEvent getNext(ITmfContext context) {
509 // return super.getNext(context);
510 // }
3d62f8b7 511
a72a38d9
ASL
512 // @Override
513 // public void queueResult(LttngSyntheticEvent data) {
514 // super.queueResult(data);
515 // }
cb866e08 516
5d10d135 517}
This page took 0.050563 seconds and 5 git commands to generate.