(no commit message)
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng / src / org / eclipse / linuxtools / lttng / control / LttngSyntheticEventProvider.java
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
13 package org.eclipse.linuxtools.lttng.control;
14
15 import java.util.HashMap;
16 import java.util.Map;
17
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.TmfDataRequest;
38 import org.eclipse.linuxtools.tmf.request.TmfEventRequest;
39 import org.eclipse.linuxtools.tmf.trace.ITmfContext;
40 import org.eclipse.linuxtools.tmf.trace.TmfContext;
41 import org.eclipse.linuxtools.tmf.trace.TmfTrace;
42
43 /**
44 * @author alvaro
45 *
46 */
47 public class LttngSyntheticEventProvider extends
48 TmfEventProvider<LttngSyntheticEvent> {
49
50 // ========================================================================
51 // Data
52 // ========================================================================
53 public static final int BLOCK_SIZE = 1;
54 public static final int NB_EVENTS = 1;
55 public static final int QUEUE_SIZE = 1; // lttng specific, one event at a
56 // time
57
58 // TmfDataProvider<LttngEvent> fExtProvider = null;
59 private ITmfDataRequest<LttngSyntheticEvent> fmainRequest = null;
60 private final Map<IStateTraceManager, LttngBaseEventRequest> feventProviderRequests = new HashMap<IStateTraceManager, LttngBaseEventRequest>();
61 private final LttngSyntheticEvent fStatusEvent;
62 private final LttngSyntheticEvent fStatusEventAck;
63 private int fmainReqEventCount = 0;
64 volatile boolean startIndSent = false;
65 private LTTngTreeNode fExperiment = null;
66 private ITransEventProcessor fstateUpdateProcessor = StateEventToHandlerFactory
67 .getInstance();
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();
85 LttngTimestamp statusTimeStamp = new LttngTimestamp(
86 TmfTimestamp.BigBang);
87
88 fStatusEvent = new LttngSyntheticEvent(null, statusTimeStamp, source,
89 dtype, null, null, null);
90 fStatusEvent.setSequenceInd(SequenceInd.STARTREQ);
91
92 fStatusEventAck = new LttngSyntheticEvent(null, statusTimeStamp,
93 source, dtype, null, null, null);
94 fStatusEventAck.setSequenceInd(SequenceInd.ACK);
95 }
96
97 // ========================================================================
98 // Methods
99 // ========================================================================
100 @SuppressWarnings("unchecked")
101 @Override
102 public ITmfContext armRequest(
103 final ITmfDataRequest<LttngSyntheticEvent> request) {
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
122 if (feventProviderRequests.size() < 1) {
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();
132
133 TraceDebug.debug("Main Synthethic event request started on thread: " + Thread.currentThread().getName());
134
135 // loop for every traceManager in current experiment
136 for (IStateTraceManager traceManager : feventProviderRequests
137 .keySet()) {
138
139 // restore trace state system to nearest check point
140 TmfTimestamp checkPoint = traceManager
141 .restoreCheckPointByTimestamp(reqWindow.getStartTime());
142 // validate so checkpoint restore is within requested bounds
143 TmfTimeRange traceRange = traceManager.getTrace().getTimeRange();
144 if (!(checkPoint.getValue() >= traceRange.getStartTime().getValue()
145 && checkPoint.getValue() <= traceRange.getEndTime()
146 .getValue() && checkPoint.getValue() < reqWindow
147 .getEndTime().getValue())) {
148 // checkpoint is out of trace bounds
149 continue;
150 }
151
152 // adjust start time bound to check point
153 TmfTimeRange adjustedRange = new TmfTimeRange(checkPoint, reqWindow
154 .getEndTime());
155
156 LttngTraceState traceModel = traceManager.getStateModel();
157 // create sub-request for one trace within experiment
158 final LttngBaseEventRequest subRequest = new LttngBaseEventRequest(
159 adjustedRange, reqWindow.getStartTime(), 0,
160 TmfEventRequest.ALL_DATA, BLOCK_SIZE, traceModel) {
161
162 private LttngSyntheticEvent syntheticEvent = null;
163 private LttngSyntheticEvent syntheticAckIndicator = null;
164 long subEventCount = 0L;
165
166 private final long fDispatchTime = getDispatchTime().getValue();
167 private final LttngTraceState fTraceModel = getTraceModel();
168
169 /*
170 * (non-Javadoc)
171 *
172 * @see
173 * org.eclipse.linuxtools.lttng.control.LttngEventRequest#handleData
174 * ()
175 */
176 @Override
177 public void handleData() {
178 LttngEvent[] events = getData();
179 if (events.length > 0) {
180 for (LttngEvent e : events) {
181 handleIncomingData(e);
182 }
183 } else {
184 TraceDebug.debug("handle data received with no data");
185 // done();
186 }
187 }
188
189 /*
190 * (non-Javadoc)
191 *
192 * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#done()
193 */
194 @Override
195 public void done() {
196 // mark this sub-request as completed
197 super.done();
198 handleProviderDone(getTraceModel());
199 }
200
201 /**
202 * Trigger the Analysis and sequential control of the events.
203 *
204 * @param e
205 */
206 private void handleIncomingData(LttngEvent e) {
207 long eventTime = e.getTimestamp().getValue();
208
209 // if (eventTime == 13589777932952L) {
210 // // syscall entry id 78 expected
211 // System.out.println("debug mark at 13589777932952L");
212 // }
213
214 // queue the new event data and an ACK
215 updateSynEvent(e);
216
217
218
219 // If time at or above requested time, update application
220 if (eventTime >= fDispatchTime) {
221 // Before update
222 syntheticEvent.setSequenceInd(SequenceInd.BEFORE);
223 queueResult(syntheticEvent);
224 queueResult(syntheticAckIndicator);
225
226 // Update state locally
227 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
228 fstateUpdateProcessor.process(syntheticEvent,
229 fTraceModel);
230
231 // After Update
232 syntheticEvent.setSequenceInd(SequenceInd.AFTER);
233 queueResult(syntheticEvent);
234 queueResult(syntheticAckIndicator);
235
236 // increment once per dispatch
237 incrementSynEvenCount();
238 subEventCount++;
239 } else {
240 // event time is between checkpoint adjusted time and
241 // requested time i.e. application does not expect the
242 // event, however the state system needs to be re-built
243 // to the dispatch point
244 syntheticEvent.setSequenceInd(SequenceInd.UPDATE);
245 fstateUpdateProcessor.process(syntheticEvent,
246 fTraceModel);
247 }
248 }
249
250 /**
251 * Create a synthetic event from the received new reference, if
252 * the reference is the same there is no need for a new instance
253 *
254 * if this is the first event for this request, call start
255 * handler
256 *
257 * @param e
258 * @return
259 */
260 private LttngSyntheticEvent updateSynEvent(LttngEvent e) {
261 if (syntheticEvent == null
262 || syntheticEvent.getBaseEvent() != e) {
263 syntheticEvent = new LttngSyntheticEvent(e);
264 syntheticAckIndicator = new LttngSyntheticEvent(e);
265 syntheticAckIndicator.setSequenceInd(SequenceInd.ACK);
266 }
267
268 // Trace model needed by application handlers
269 syntheticEvent.setTraceModel(fTraceModel);
270
271 // send the start request indication once per request thread
272 if (!startIndSent) {
273 TraceDebug.debug("Thread started: " + Thread.currentThread().getName());
274 handleProviderStarted(getTraceModel());
275 startIndSent = true;
276 }
277
278 return syntheticEvent;
279 }
280 };
281
282 // preserve the associated sub request to control it e.g.
283 // cancellation
284 feventProviderRequests.put(traceManager, subRequest);
285
286 // start request
287 TmfTrace<LttngEvent> provider = (TmfTrace<LttngEvent>) traceManager
288 .getTrace();
289 provider.sendRequest(subRequest);
290 }
291
292 // Return a dummy context, not used for relay provider
293 return new TmfContext();
294 }
295
296 /**
297 * Notify listeners to prepare to receive data e.g. clean previous data etc.
298 */
299 public void handleProviderStarted(LttngTraceState traceModel) {
300 LttngSyntheticEvent startIndEvent = new LttngSyntheticEvent(
301 fStatusEvent);
302 startIndEvent.setSequenceInd(SequenceInd.STARTREQ);
303
304 // Notify application
305 queueResult(startIndEvent);
306 queueResult(fStatusEventAck);
307
308 // Notify state event processor
309 fstateUpdateProcessor.process(startIndEvent, null);
310 }
311
312 /**
313 * Notify listeners, no more events for the current request will be
314 * distributed e.g. update view.
315 */
316 public synchronized void handleProviderDone(LttngTraceState traceModel) {
317 // TODO: The use of a thread per main request and thread per sub-request
318 // requires
319 // to make sure the proper main request is marked completed. So a
320 // relationship of sub-requests to parent needs to be established to
321 // handle completion and cancellations properly
322
323 // Close the main request when all sub-requests are marked completed
324 for (LttngBaseEventRequest subRequest : feventProviderRequests.values()) {
325 if (subRequest != null) {
326 if (!subRequest.isCompleted()) {
327 // Not ready to complete main request
328 return;
329 }
330 }
331 }
332
333 // All sub-requests are marked completed so the main request can be
334 // completed as well
335 // Notify application,
336 LttngSyntheticEvent finishEvent = new LttngSyntheticEvent(fStatusEvent);
337 finishEvent.setSequenceInd(SequenceInd.ENDREQ);
338 finishEvent.setTraceModel(traceModel);
339 queueResult(finishEvent);
340 queueResult(fStatusEventAck);
341 // End the loop in the main request
342 queueResult(LttngSyntheticEvent.NullEvent);
343 }
344
345 /**
346 * Increment the global event counter i.e. events from any sub requests
347 */
348 private synchronized void incrementSynEvenCount() {
349 fmainReqEventCount++;
350 }
351
352 /**
353 * @return
354 */
355 public synchronized int getSynEvenCount() {
356 return fmainReqEventCount;
357 }
358
359 /**
360 * Reset provider to a state ready to begin thread execution
361 *
362 * @param experimentNode
363 */
364 public /* synchronized */ void reset(LTTngTreeNode experimentNode) {
365
366 fmainRequest = null;
367
368 // Make sure previous request are terminated
369 for (LttngBaseEventRequest tmpRequest : feventProviderRequests.values()) {
370 if (tmpRequest != null && !tmpRequest.isCompleted()) {
371 tmpRequest.cancel();
372 }
373 }
374
375 feventProviderRequests.clear();
376 fmainReqEventCount = 0;
377 startIndSent = false;
378
379 // set of base event providers
380 if (fExperiment != null) {
381 LTTngTreeNode[] traces = fExperiment.getChildren();
382 for (LTTngTreeNode trace : traces) {
383 IStateTraceManager traceBaseEventProvider = (IStateTraceManager) trace;
384 feventProviderRequests.put(traceBaseEventProvider, null);
385 }
386 }
387
388 if (fExperiment != experimentNode) {
389 updateExperimentNode(experimentNode);
390 }
391 }
392
393 /**
394 * Point to a new experiment reference
395 *
396 * @param experiment
397 */
398 private synchronized void updateExperimentNode(LTTngTreeNode experiment) {
399 if (experiment != null
400 && experiment.getValue() instanceof TmfExperiment<?>) {
401 fExperiment = experiment;
402 } else {
403 TraceDebug
404 .debug("Experiment received is not instance of TmfExperiment: "
405 + experiment.getClass().getName());
406 }
407 }
408
409 /*
410 * (non-Javadoc)
411 *
412 * @see
413 * org.eclipse.linuxtools.tmf.component.TmfDataProvider#sendRequest(org.
414 * eclipse.linuxtools.tmf.request.TmfDataRequest)
415 */
416 public void sendRequest(final TmfDataRequest<LttngSyntheticEvent> request) {
417 super.sendRequest(request);
418 if (waitForRequest) {
419 try {
420 request.waitForCompletion();
421 } catch (InterruptedException e) {
422 e.printStackTrace();
423 }
424 }
425 }
426
427 /**
428 * @return the waitForRequest
429 */
430 public boolean isWaitForRequest() {
431 return waitForRequest;
432 }
433
434 /**
435 * @param waitForRequest
436 * configures the provider to wait for the request completion
437 */
438 public void setWaitForRequest(boolean waitForRequest) {
439 this.waitForRequest = waitForRequest;
440 }
441
442 }
This page took 0.041753 seconds and 5 git commands to generate.