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