1 /*******************************************************************************
2 * Copyright (c) 2010 Ericsson
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
10 * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.lttng
.control
;
15 import java
.util
.HashMap
;
18 import org
.eclipse
.linuxtools
.lttng
.TraceDebug
;
19 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
20 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEventType
;
21 import org
.eclipse
.linuxtools
.lttng
.event
.LttngSyntheticEvent
;
22 import org
.eclipse
.linuxtools
.lttng
.event
.LttngSyntheticEvent
.SequenceInd
;
23 import org
.eclipse
.linuxtools
.lttng
.event
.LttngTimestamp
;
24 import org
.eclipse
.linuxtools
.lttng
.model
.LTTngTreeNode
;
25 import org
.eclipse
.linuxtools
.lttng
.request
.LttngBaseEventRequest
;
26 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.ITransEventProcessor
;
27 import org
.eclipse
.linuxtools
.lttng
.state
.evProcessor
.state
.StateEventToHandlerFactory
;
28 import org
.eclipse
.linuxtools
.lttng
.state
.model
.LttngTraceState
;
29 import org
.eclipse
.linuxtools
.lttng
.state
.trace
.IStateTraceManager
;
30 import org
.eclipse
.linuxtools
.tmf
.component
.TmfEventProvider
;
31 import org
.eclipse
.linuxtools
.tmf
.event
.TmfEventSource
;
32 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
33 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
34 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperiment
;
35 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfDataRequest
;
36 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfEventRequest
;
37 import org
.eclipse
.linuxtools
.tmf
.request
.TmfEventRequest
;
38 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfEndSynchSignal
;
39 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfStartSynchSignal
;
40 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfContext
;
41 import org
.eclipse
.linuxtools
.tmf
.trace
.ITmfTrace
;
42 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfContext
;
43 import org
.eclipse
.linuxtools
.tmf
.trace
.TmfTrace
;
49 public class LttngSyntheticEventProvider
extends TmfEventProvider
<LttngSyntheticEvent
> {
51 // ========================================================================
53 // ========================================================================
54 public static final int BLOCK_SIZE
= 1;
55 public static final int NB_EVENTS
= 1;
56 public static final int QUEUE_SIZE
= 1; // lttng specific, one event at a
59 // TmfDataProvider<LttngEvent> fExtProvider = null;
60 private ITmfDataRequest
<LttngSyntheticEvent
> fmainRequest
= null;
61 private final Map
<IStateTraceManager
, LttngBaseEventRequest
> fEventProviderRequests
= new HashMap
<IStateTraceManager
, LttngBaseEventRequest
>();
62 private final LttngSyntheticEvent fStatusEvent
;
63 private final LttngSyntheticEvent fStatusEventAck
;
64 private int fMainReqEventCount
= 0;
65 volatile boolean startIndSent
= false;
66 private LTTngTreeNode fExperiment
= null;
67 private ITransEventProcessor fstateUpdateProcessor
= StateEventToHandlerFactory
.getInstance();
68 private boolean waitForRequest
= false;
70 // ========================================================================
72 // ========================================================================
74 * Accessibility to package - use factory instead of this constructor
78 LttngSyntheticEventProvider(Class
<LttngSyntheticEvent
> type
) {
79 super("LttngSyntheticEventProvider", type
, QUEUE_SIZE
);
81 // prepare empty instance status indicators and allow them to travel via
83 TmfEventSource source
= new TmfEventSource(this);
84 LttngEventType dtype
= new LttngEventType();
85 LttngTimestamp statusTimeStamp
= new LttngTimestamp(TmfTimestamp
.Zero
);
87 fStatusEvent
= new LttngSyntheticEvent(null, statusTimeStamp
, source
, dtype
, null, null, null);
88 fStatusEvent
.setSequenceInd(SequenceInd
.STARTREQ
);
90 fStatusEventAck
= new LttngSyntheticEvent(null, statusTimeStamp
, source
, dtype
, null, null, null);
91 fStatusEventAck
.setSequenceInd(SequenceInd
.ACK
);
94 // ========================================================================
96 // ========================================================================
98 @SuppressWarnings("unchecked")
100 public ITmfContext
armRequest(final ITmfDataRequest
<LttngSyntheticEvent
> request
) {
102 // make sure we have the right type of request
103 if (!(request
instanceof ITmfEventRequest
<?
>)) {
105 TraceDebug
.debug("Request is not an instance of ITmfEventRequest");
109 if (fExperiment
== null) {
110 TraceDebug
.debug("Experiment is null");
115 // get ready to start processing
118 // At least one base provider shall be available
119 if (fEventProviderRequests
.size() < 1) {
121 TraceDebug
.debug("No Base event providers available");
125 fmainRequest
= request
;
126 // define event data handling
127 ITmfEventRequest
<LttngSyntheticEvent
> eventRequest
= (ITmfEventRequest
<LttngSyntheticEvent
>) fmainRequest
;
128 TmfTimeRange reqWindow
= eventRequest
.getRange();
130 TraceDebug
.debug("Main Synthethic event request started on thread: " + Thread
.currentThread().getName());
132 // loop for every traceManager in current experiment
133 boolean subRequestQueued
= false;
134 TmfExperiment
<LttngEvent
> experiment
= (TmfExperiment
<LttngEvent
>) fExperiment
.getValue();
135 experiment
.startSynch(new TmfStartSynchSignal(0));
136 for (IStateTraceManager traceManager
: fEventProviderRequests
.keySet()) {
138 // restore trace state system to nearest check point
139 TmfTimestamp checkPoint
= traceManager
.restoreCheckPointByTimestamp(reqWindow
.getStartTime());
141 // adjust start time bound to check point
143 // validate so checkpoint restore is within requested bounds
144 TmfTimeRange traceRange
= traceManager
.getTrace().getTimeRange();
145 if ((checkPoint
!= null) && !(
146 checkPoint
.getValue() >= traceRange
.getStartTime().getValue() &&
147 checkPoint
.getValue() <= traceRange
.getEndTime().getValue() &&
148 checkPoint
.getValue() < reqWindow
.getEndTime().getValue())
150 // checkpoint is out of trace bounds
153 TmfTimeRange adjustedRange
= reqWindow
;
154 if (checkPoint
!= null) {
155 adjustedRange
= new TmfTimeRange(checkPoint
, reqWindow
.getEndTime());
158 LttngTraceState traceModel
= traceManager
.getStateModel();
159 // String key = (traceManager.getTrace().getPath() +
160 // traceManager.getTrace().getName()).hashCode();
161 ITmfTrace trace
= traceManager
.getTrace();
162 // create sub-request for one trace within experiment
163 final LttngBaseEventRequest subRequest
= new LttngBaseEventRequest(adjustedRange
, reqWindow
.getStartTime(),
164 0, TmfEventRequest
.ALL_DATA
, BLOCK_SIZE
, traceModel
, ITmfDataRequest
.ExecutionType
.FOREGROUND
, trace
) {
166 private LttngSyntheticEvent syntheticEvent
= null;
167 private LttngSyntheticEvent syntheticAckIndicator
= null;
168 long subEventCount
= 0L;
170 private final long fDispatchTime
= getDispatchTime().getValue();
171 private final LttngTraceState fTraceModel
= getTraceModel();
172 private LttngSyntheticEvent
[] fresult
= new LttngSyntheticEvent
[1];
177 * @see org.eclipse.linuxtools.lttng.control.LttngEventRequest#handleData ()
180 public void handleData() {
181 LttngEvent
[] events
= getData();
183 // Tracer.trace("Sep: " + events[0].getTimestamp());
185 if (events
.length
> 0) {
186 handleIncomingData(events
[0]);
188 TraceDebug
.debug("handle data received with no data");
189 // handleProviderDone(getTraceModel());
197 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#done()
201 // mark this sub-request as completed
203 handleProviderDone();
208 * Trigger the Analysis and sequential control of the events.
212 private void handleIncomingData(LttngEvent e
) {
213 long eventTime
= e
.getTimestamp().getValue();
215 TmfTrace
<LttngEvent
> inTrace
= e
.getParentTrace();
216 if (!(inTrace
== getTrace())) {
217 // System.out.println("Event from a different trace discarded");
221 // queue the new event data and an ACK
224 // If time at or above requested time, update application
225 if (eventTime
>= fDispatchTime
) {
226 // Load synthetic event as the result data
227 fresult
[0] = syntheticEvent
;
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
);
234 fmainRequest
.handleData();
235 // result[0] = syntheticAckIndicator;
236 // fmainRequest.setData(result);
237 // fmainRequest.handleData();
239 // STATE UPDATE: local handlers
240 syntheticEvent
.setSequenceInd(SequenceInd
.UPDATE
);
241 fstateUpdateProcessor
.process(syntheticEvent
, fTraceModel
);
243 // AFTER UPDATE: update to the after state-update handlers
244 syntheticEvent
.setSequenceInd(SequenceInd
.AFTER
);
245 // queueResult(syntheticEvent);
246 // queueResult(syntheticAckIndicator);
247 fmainRequest
.setData(fresult
);
248 fmainRequest
.handleData();
249 // result[0] = syntheticAckIndicator;
250 // fmainRequest.setData(result);
251 // fmainRequest.handleData();
253 // increment once per dispatch
254 incrementSynEvenCount();
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
);
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
270 * if this is the first event for this request, call start handler
275 private LttngSyntheticEvent
updateSynEvent(LttngEvent e
) {
276 if (syntheticEvent
== null || syntheticEvent
.getBaseEvent() != e
) {
277 syntheticEvent
= new LttngSyntheticEvent(e
);
278 syntheticAckIndicator
= new LttngSyntheticEvent(e
);
279 syntheticAckIndicator
.setSequenceInd(SequenceInd
.ACK
);
282 // Trace model needed by application handlers
283 syntheticEvent
.setTraceModel(fTraceModel
);
285 // send the start request indication once per request thread
287 TraceDebug
.debug("Thread started: " + Thread
.currentThread().getName());
288 handleProviderStarted(getTraceModel());
292 return syntheticEvent
;
296 // preserve the associated sub request to control it e.g.
298 fEventProviderRequests
.put(traceManager
, subRequest
);
301 TmfExperiment
<LttngEvent
> provider
= (TmfExperiment
<LttngEvent
>) fExperiment
.getValue();
302 provider
.sendRequest(subRequest
);
304 // provider.sendRequest(subRequest, ExecutionType.LONG);
305 subRequestQueued
= true;
308 experiment
.endSynch(new TmfEndSynchSignal(0));
310 // Return a dummy context, not used for relay provider
311 return (subRequestQueued
) ?
new TmfContext() : null;
315 * Notify listeners to prepare to receive data e.g. clean previous data etc.
317 public void handleProviderStarted(LttngTraceState traceModel
) {
318 LttngSyntheticEvent startIndEvent
= new LttngSyntheticEvent(fStatusEvent
);
319 startIndEvent
.setSequenceInd(SequenceInd
.STARTREQ
);
321 // Notify application
322 LttngSyntheticEvent
[] result
= new LttngSyntheticEvent
[1];
323 result
[0] = startIndEvent
;
324 fmainRequest
.setData(result
);
325 fmainRequest
.handleData();
326 // result[0] = fStatusEventAck;
327 // fmainRequest.setData(result);
328 // fmainRequest.handleData();
331 // queueResult(startIndEvent);
332 // queueResult(fStatusEventAck);
333 // } catch (InterruptedException e) {
334 // // TODO: cancel this request
335 // e.printStackTrace();
338 // Notify state event processor
339 fstateUpdateProcessor
.process(startIndEvent
, null);
343 * Notify listeners, no more events for the current request will be distributed e.g. update view.
345 public synchronized void handleProviderDone() {
346 // TODO: The use of a thread per main request and thread per sub-request
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
352 // Close the main request when all sub-requests are marked completed
353 for (LttngBaseEventRequest subRequest
: fEventProviderRequests
.values()) {
354 if (subRequest
!= null) {
355 if (!subRequest
.isCompleted()) {
356 // Not ready to complete main request
362 // Notify application. One notification per trace so the last state of each trace can be
364 LttngTraceState traceModel
;
365 for (IStateTraceManager traceMgr
: fEventProviderRequests
.keySet()) {
366 traceModel
= traceMgr
.getStateModel();
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
);
374 LttngSyntheticEvent
[] result
= new LttngSyntheticEvent
[1];
375 // End Request indication
376 result
[0] = finishEvent
;
377 fmainRequest
.setData(result
);
378 fmainRequest
.handleData();
380 // // End Request processed indication
381 // result[0] = fStatusEventAck;
382 // fmainRequest.setData(result);
383 // fmainRequest.handleData();
386 // All sub-requests are marked completed so the main request can be completed as well
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();
403 * Increment the global event counter i.e. events from any sub requests
405 private synchronized void incrementSynEvenCount() {
406 fMainReqEventCount
++;
412 public synchronized int getSynEvenCount() {
413 return fMainReqEventCount
;
417 * Reset provider to a state ready to begin thread execution
419 * @param experimentNode
421 public synchronized void reset(LTTngTreeNode experimentNode
) {
425 // Make sure previous request are terminated
426 for (LttngBaseEventRequest tmpRequest
: fEventProviderRequests
.values()) {
427 if (tmpRequest
!= null && !tmpRequest
.isCompleted()) {
432 fEventProviderRequests
.clear();
433 fMainReqEventCount
= 0;
434 startIndSent
= false;
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
;
441 fEventProviderRequests
.put(traceBaseEventProvider
, null);
445 if (fExperiment
!= experimentNode
) {
446 updateExperimentNode(experimentNode
);
451 * Point to a new experiment reference
455 private synchronized void updateExperimentNode(LTTngTreeNode experiment
) {
456 if (experiment
!= null && experiment
.getValue() instanceof TmfExperiment
<?
>) {
457 fExperiment
= experiment
;
460 .debug("Experiment received is not instance of TmfExperiment: " + experiment
.getClass().getName());
467 * @see org.eclipse.linuxtools.tmf.component.TmfDataProvider#sendRequest(org.
468 * eclipse.linuxtools.tmf.request.TmfDataRequest)
471 public void sendRequest(final ITmfDataRequest
<LttngSyntheticEvent
> request
) {
472 super.sendRequest(request
);
473 if (waitForRequest
) {
475 request
.waitForCompletion();
476 } catch (InterruptedException e
) {
483 * @return the waitForRequest
485 public boolean isWaitForRequest() {
486 return waitForRequest
;
490 * @param waitForRequest
491 * configures the provider to wait for the request completion
493 public void setWaitForRequest(boolean waitForRequest
) {
494 this.waitForRequest
= waitForRequest
;
498 public LttngSyntheticEvent
getNext(ITmfContext context
) {
500 fmainRequest
.waitForCompletion();
501 } catch (InterruptedException e
) {
508 // public LttngSyntheticEvent getNext(ITmfContext context) {
509 // return super.getNext(context);
513 // public void queueResult(LttngSyntheticEvent data) {
514 // super.queueResult(data);