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