tmf: only dispatch events to relevant event providers
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / request / TmfEventRequest.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2013 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 * Francois Chouinard - Initial API and implementation
11 * Alexandre Montplaisir - Consolidate constructors, merge with TmfDataRequest
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.tmf.core.request;
15
16 import java.util.concurrent.CountDownLatch;
17
18 import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer;
19 import org.eclipse.tracecompass.tmf.core.component.ITmfEventProvider;
20 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
21 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
22
23 /**
24 * TmfEventRequest's are used to obtain series of events from an event provider.
25 * Open ranges can be used, especially for continuous streaming.
26 * <p>
27 * The request is processed asynchronously by a TmfEventProvider and, as events
28 * become available, handleData() is invoked synchronously for each one.
29 * <p>
30 * The TmfEventProvider indicates that the request is completed by calling
31 * done(). The request can be cancelled at any time with cancel().
32 * <p>
33 * Typical usage:
34 *
35 * <pre><code>
36 * TmfEventRequest request = new TmfEventRequest(DataType.class, range, startIndex, nbEvents, priority) {
37 *
38 * public void handleData(ITmfEvent event) {
39 * // do something with the event
40 * }
41 *
42 * public void handleSuccess() {
43 * // callback for when the request completes successfully
44 * }
45 *
46 * public void handleFailure() {
47 * // callback for when the request fails due to an error
48 * }
49 *
50 * public void handleCancel() {
51 * // callback for when the request is cancelled via .cancel()
52 * }
53 *
54 * };
55 *
56 * eventProvider.sendRequest(request);
57 * </code></pre>
58 *
59 *
60 * TODO: Implement request failures (codes, etc...)
61 *
62 * @author Francois Chouinard
63 * @since 3.0
64 */
65 public abstract class TmfEventRequest implements ITmfEventRequest {
66
67 // ------------------------------------------------------------------------
68 // Constants
69 // ------------------------------------------------------------------------
70
71 private static int fRequestNumber = 0;
72
73 // ------------------------------------------------------------------------
74 // Attributes
75 // ------------------------------------------------------------------------
76
77 private final Class<? extends ITmfEvent> fDataType;
78 private final ExecutionType fExecType;
79
80 /** A unique request ID */
81 private final int fRequestId;
82
83 /** The requested events time range */
84 private final TmfTimeRange fRange;
85
86 /** The index (rank) of the requested event
87 * @since 3.0*/
88 protected long fIndex;
89
90 /** The number of requested events (ALL_DATA for all)
91 * @since 3.0*/
92 protected int fNbRequested;
93
94 /** The number of reads so far */
95 private int fNbRead;
96
97 private final CountDownLatch startedLatch = new CountDownLatch(1);
98 private final CountDownLatch completedLatch = new CountDownLatch(1);
99
100 private boolean fRequestRunning;
101 private boolean fRequestCompleted;
102 private boolean fRequestFailed;
103 private boolean fRequestCanceled;
104
105 private ITmfEventProvider fEventProvider;
106
107 // ------------------------------------------------------------------------
108 // Constructors
109 // ------------------------------------------------------------------------
110
111 /**
112 * Request 'n' events of a given type, for the *whole* trace, at the given
113 * priority.
114 *
115 * @param dataType
116 * The requested data type.
117 * @param index
118 * The index of the first event to retrieve. You can use '0' to
119 * start at the beginning of the trace.
120 * @param nbRequested
121 * The number of events requested. You can use
122 * {@link TmfEventRequest#ALL_DATA} to indicate you want all
123 * events in the trace.
124 * @param priority
125 * The requested execution priority.
126 */
127 public TmfEventRequest(Class<? extends ITmfEvent> dataType,
128 long index,
129 int nbRequested,
130 ExecutionType priority) {
131 this(dataType, TmfTimeRange.ETERNITY, index, nbRequested, priority);
132 }
133
134 /**
135 * Request 'n' events of a given type, for the given time range, at the
136 * given priority.
137 *
138 * @param dataType
139 * The requested data type.
140 * @param range
141 * The time range of the requested events. You can use
142 * {@link TmfTimeRange#ETERNITY} to indicate you want to cover
143 * the whole trace.
144 * @param index
145 * The index of the first event to retrieve. You can use '0' to
146 * start at the beginning of the trace.
147 * @param nbRequested
148 * The number of events requested. You can use
149 * {@link TmfEventRequest#ALL_DATA} to indicate you want all
150 * events in the time range.
151 * @param priority
152 * The requested execution priority.
153 */
154 public TmfEventRequest(Class<? extends ITmfEvent> dataType,
155 TmfTimeRange range,
156 long index,
157 int nbRequested,
158 ExecutionType priority) {
159
160 synchronized (this.getClass()) {
161 fRequestId = fRequestNumber++;
162 }
163 fDataType = dataType;
164 fIndex = index;
165 fNbRequested = nbRequested;
166 fExecType = priority;
167 fRange = range;
168 fNbRead = 0;
169
170 fRequestRunning = false;
171 fRequestCompleted = false;
172 fRequestFailed = false;
173 fRequestCanceled = false;
174
175 /* Setup the request tracing if it's enabled */
176 if (TmfCoreTracer.isRequestTraced()) {
177 String type = getClass().getName();
178 type = type.substring(type.lastIndexOf('.') + 1);
179 @SuppressWarnings("nls")
180 String message = "CREATED "
181 + (getExecType() == ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
182 + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
183 + " Range=" + getRange()
184 + " DataType=" + getDataType().getSimpleName();
185 TmfCoreTracer.traceRequest(fRequestId, message);
186 }
187 }
188
189 /**
190 * Resets the request counter (used for testing)
191 */
192 public static synchronized void reset() {
193 fRequestNumber = 0;
194 }
195
196 // ------------------------------------------------------------------------
197 // Accessors
198 // ------------------------------------------------------------------------
199
200 @Override
201 public int getRequestId() {
202 return fRequestId;
203 }
204
205 @Override
206 public long getIndex() {
207 return fIndex;
208 }
209
210 /**
211 * @since 3.0
212 */
213 @Override
214 public ExecutionType getExecType() {
215 return fExecType;
216 }
217
218 @Override
219 public int getNbRequested() {
220 return fNbRequested;
221 }
222
223 @Override
224 public synchronized int getNbRead() {
225 return fNbRead;
226 }
227
228 @Override
229 public synchronized boolean isRunning() {
230 return fRequestRunning;
231 }
232
233 @Override
234 public synchronized boolean isCompleted() {
235 return fRequestCompleted;
236 }
237
238 @Override
239 public synchronized boolean isFailed() {
240 return fRequestFailed;
241 }
242
243 @Override
244 public synchronized boolean isCancelled() {
245 return fRequestCanceled;
246 }
247
248 @Override
249 public Class<? extends ITmfEvent> getDataType() {
250 return fDataType;
251 }
252
253 @Override
254 public TmfTimeRange getRange() {
255 return fRange;
256 }
257
258 /**
259 * @since 3.0
260 */
261 @Override
262 public ITmfEventProvider getEventProvider() {
263 return fEventProvider;
264 }
265
266 /**
267 * @since 3.0
268 */
269 @Override
270 public void setEventProvider(ITmfEventProvider provider) {
271 fEventProvider = provider;
272 }
273
274 // ------------------------------------------------------------------------
275 // Setters
276 // ------------------------------------------------------------------------
277
278 /**
279 * This method is called by the event provider to set the index
280 * corresponding to the time range start time
281 *
282 * @param index
283 * The start time index
284 */
285 protected void setIndex(int index) {
286 fIndex = index;
287 }
288
289 @Override
290 public void setStartIndex(int index) {
291 setIndex(index);
292 }
293
294 // ------------------------------------------------------------------------
295 // Operators
296 // ------------------------------------------------------------------------
297
298 @Override
299 public void handleData(ITmfEvent event) {
300 fNbRead++;
301 }
302
303 @Override
304 public void handleStarted() {
305 if (TmfCoreTracer.isRequestTraced()) {
306 TmfCoreTracer.traceRequest(getRequestId(), "STARTED"); //$NON-NLS-1$
307 }
308 }
309
310 @Override
311 public void handleCompleted() {
312 boolean requestFailed = false;
313 boolean requestCanceled = false;
314 synchronized (this) {
315 requestFailed = fRequestFailed;
316 requestCanceled = fRequestCanceled;
317 }
318
319 if (requestFailed) {
320 handleFailure();
321 } else if (requestCanceled) {
322 handleCancel();
323 } else {
324 handleSuccess();
325 }
326 if (TmfCoreTracer.isRequestTraced()) {
327 TmfCoreTracer.traceRequest(getRequestId(), "COMPLETED (" + fNbRead + " events read)"); //$NON-NLS-1$ //$NON-NLS-2$
328 }
329 }
330
331 @Override
332 public void handleSuccess() {
333 if (TmfCoreTracer.isRequestTraced()) {
334 TmfCoreTracer.traceRequest(getRequestId(), "SUCCEEDED"); //$NON-NLS-1$
335 }
336 }
337
338 @Override
339 public void handleFailure() {
340 if (TmfCoreTracer.isRequestTraced()) {
341 TmfCoreTracer.traceRequest(getRequestId(), "FAILED"); //$NON-NLS-1$
342 }
343 }
344
345 @Override
346 public void handleCancel() {
347 if (TmfCoreTracer.isRequestTraced()) {
348 TmfCoreTracer.traceRequest(getRequestId(), "CANCELLED"); //$NON-NLS-1$
349 }
350 }
351
352 /**
353 * To suspend the client thread until the request starts (or is canceled).
354 *
355 * @throws InterruptedException
356 * If the thread was interrupted while waiting
357 */
358 public void waitForStart() throws InterruptedException {
359 while (!fRequestRunning) {
360 startedLatch.await();
361 }
362 }
363
364 @Override
365 public void waitForCompletion() throws InterruptedException {
366 while (!fRequestCompleted) {
367 completedLatch.await();
368 }
369 }
370
371 @Override
372 public void start() {
373 synchronized (this) {
374 fRequestRunning = true;
375 }
376 handleStarted();
377 startedLatch.countDown();
378 }
379
380 @Override
381 public void done() {
382 synchronized (this) {
383 if (!fRequestCompleted) {
384 fRequestRunning = false;
385 fRequestCompleted = true;
386 } else {
387 return;
388 }
389 }
390 try {
391 handleCompleted();
392 } finally {
393 completedLatch.countDown();
394 }
395 }
396
397 @Override
398 public void fail() {
399 synchronized (this) {
400 fRequestFailed = true;
401 }
402 done();
403 }
404
405 @Override
406 public void cancel() {
407 synchronized (this) {
408 fRequestCanceled = true;
409 }
410 done();
411 }
412
413 // ------------------------------------------------------------------------
414 // Object
415 // ------------------------------------------------------------------------
416
417 @Override
418 // All requests have a unique id
419 public int hashCode() {
420 return getRequestId();
421 }
422
423 @Override
424 public boolean equals(Object other) {
425 if (other instanceof TmfEventRequest) {
426 TmfEventRequest request = (TmfEventRequest) other;
427 return request.fDataType == fDataType
428 && request.fIndex == fIndex
429 && request.fNbRequested == fNbRequested
430 && request.fRange.equals(fRange);
431 }
432 return false;
433 }
434
435 @Override
436 public String toString() {
437 String name = getClass().getName();
438 int dot = name.lastIndexOf('.');
439 if (dot >= 0) {
440 name = name.substring(dot + 1);
441 }
442 return '[' + name + '(' + getRequestId() + ',' + getDataType().getSimpleName() +
443 ',' + getExecType() + ',' + getRange() + ',' + getIndex() +
444 ',' + getNbRequested() + ")]"; //$NON-NLS-1$
445 }
446
447 }
This page took 0.042026 seconds and 6 git commands to generate.