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