lttng: More luna annotation updates
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / request / TmfDataRequest.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 - Consolidated constructors
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
21 /**
22 * TmfDataRequests are used to obtain blocks of contiguous data from a data
23 * provider. Open ranges can be used, especially for continuous streaming.
24 * <p>
25 * The request is processed asynchronously by a TmfProvider and, as blocks of
26 * data become available, handleData() is invoked synchronously for each block.
27 * Upon return, the data instances go out of scope and become eligible for gc.
28 * It is is thus the responsibility of the requester to either clone or keep a
29 * reference to the data it wishes to track specifically.
30 * <p>
31 * This data block approach is used to avoid busting the heap for very large
32 * trace files. The block size is configurable.
33 * <p>
34 * The TmfProvider indicates that the request is completed by calling done().
35 * The request can be canceled at any time with cancel().
36 * <p>
37 * Typical usage:
38 *
39 * <pre>
40 * <code><i>TmfTimeWindow range = new TmfTimewindow(...);
41 * TmfDataRequest&lt;DataType[]&gt; request = new TmfDataRequest&lt;DataType[]&gt;(DataType.class, 0, NB_EVENTS, BLOCK_SIZE) {
42 * public void handleData() {
43 * DataType[] data = request.getData();
44 * for (DataType e : data) {
45 * // do something
46 * }
47 * }
48 * public void handleSuccess() {
49 * // do something
50 * }
51 * }
52 * public void handleFailure() {
53 * // do something
54 * }
55 * }
56 * public void handleCancel() {
57 * // do something
58 * }
59 * }
60 * };
61 * fProcessor.process(request, true);
62 * </i></code>
63 * </pre>
64 *
65 * TODO: Consider decoupling from "time range", "rank", etc and for the more
66 * generic notion of "criteria". This would allow to extend for "time range",
67 * etc instead of providing specialized constructors. This also means removing
68 * the criteria info from the data structure (with the possible exception of
69 * fNbRequested). The nice thing about it is that it would prepare us well for
70 * the coming generation of analysis tools.
71 *
72 * TODO: Implement request failures (codes, etc...)
73 *
74 * @version 1.0
75 * @author Francois Chouinard
76 */
77 public abstract class TmfDataRequest implements ITmfDataRequest {
78
79 // ------------------------------------------------------------------------
80 // Constants
81 // ------------------------------------------------------------------------
82
83 /** The request count for all the events */
84 public static final int ALL_DATA = Integer.MAX_VALUE;
85
86 private static int fRequestNumber = 0;
87
88 // ------------------------------------------------------------------------
89 // Attributes
90 // ------------------------------------------------------------------------
91
92 private final Class<? extends ITmfEvent> fDataType;
93 private final ExecutionType fExecType;
94
95 /** A unique request ID */
96 private final int fRequestId;
97
98 /** The index (rank) of the requested event */
99 protected long fIndex;
100
101 /** The number of requested events (ALL_DATA for all) */
102 protected int fNbRequested;
103
104 /** The number of reads so far */
105 private int fNbRead;
106
107 private final CountDownLatch startedLatch = new CountDownLatch(1);
108 private final CountDownLatch completedLatch = new CountDownLatch(1);
109 private boolean fRequestRunning;
110 private boolean fRequestCompleted;
111 private boolean fRequestFailed;
112 private boolean fRequestCanceled;
113
114 // ------------------------------------------------------------------------
115 // Constructors
116 // ------------------------------------------------------------------------
117
118 /**
119 * Resets the request counter (used for testing)
120 */
121 public static void reset() {
122 fRequestNumber = 0;
123 }
124
125 /**
126 * Request 'n' events of a given type from the given index (given priority).
127 * Events are returned in blocks of the given size.
128 *
129 * @param dataType
130 * The requested data type.
131 * @param index
132 * The index of the first event to retrieve. Use '0' to start at
133 * the beginning of the trace.
134 * @param nbRequested
135 * The number of events requested. You can use
136 * {@link TmfDataRequest#ALL_DATA} to specify you want all events
137 * in the trace.
138 * @param priority
139 * The requested execution priority.
140 */
141 public TmfDataRequest(Class<? extends ITmfEvent> dataType,
142 long index,
143 int nbRequested,
144 ExecutionType priority) {
145 fRequestId = fRequestNumber++;
146 fDataType = dataType;
147 fIndex = index;
148 fNbRequested = nbRequested;
149 fExecType = priority;
150 fNbRead = 0;
151
152 fRequestRunning = false;
153 fRequestCompleted = false;
154 fRequestFailed = false;
155 fRequestCanceled = false;
156
157 if (!(this instanceof ITmfEventRequest) && TmfCoreTracer.isRequestTraced()) {
158 String type = getClass().getName();
159 type = type.substring(type.lastIndexOf('.') + 1);
160 @SuppressWarnings("nls")
161 String message = "CREATED "
162 + (getExecType() == ITmfDataRequest.ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
163 + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
164 + " DataType=" + getDataType().getSimpleName();
165 TmfCoreTracer.traceRequest(this, message);
166 }
167 }
168
169 // ------------------------------------------------------------------------
170 // Accessors
171 // ------------------------------------------------------------------------
172
173 /**
174 * @return the request ID
175 */
176 @Override
177 public int getRequestId() {
178 return fRequestId;
179 }
180
181 /**
182 * @return the index of the first event requested
183 */
184 @Override
185 public long getIndex() {
186 return fIndex;
187 }
188
189 /**
190 * @return the execution type (priority)
191 */
192 @Override
193 public ExecutionType getExecType() {
194 return fExecType;
195 }
196
197 /**
198 * @return the number of requested events (ALL_DATA = all)
199 */
200 @Override
201 public int getNbRequested() {
202 return fNbRequested;
203 }
204
205 /**
206 * @return the number of events read so far
207 */
208 @Override
209 public synchronized int getNbRead() {
210 return fNbRead;
211 }
212
213 /**
214 * @return indicates if the request is currently running
215 */
216 @Override
217 public synchronized boolean isRunning() {
218 return fRequestRunning;
219 }
220
221 /**
222 * @return indicates if the request is completed
223 */
224 @Override
225 public synchronized boolean isCompleted() {
226 return fRequestCompleted;
227 }
228
229 /**
230 * @return indicates if the request has failed
231 */
232 @Override
233 public synchronized boolean isFailed() {
234 return fRequestFailed;
235 }
236
237 /**
238 * @return indicates if the request is canceled
239 */
240 @Override
241 public synchronized boolean isCancelled() {
242 return fRequestCanceled;
243 }
244
245 /**
246 * @return the requested data type
247 */
248 @Override
249 public Class<? extends ITmfEvent> getDataType() {
250 return fDataType;
251 }
252
253 // ------------------------------------------------------------------------
254 // Setters
255 // ------------------------------------------------------------------------
256
257 /**
258 * this method is called by the event provider to set the index corresponding to the time range start time
259 *
260 * @param index
261 * the start time index
262 */
263 protected void setIndex(int index) {
264 fIndex = index;
265 }
266
267 // ------------------------------------------------------------------------
268 // Operators
269 // ------------------------------------------------------------------------
270
271 /**
272 * Handle incoming data, one event at a time i.e. this method is invoked
273 * for every data item obtained by the request.
274 *
275 * - Data items are received in the order they appear in the stream
276 * - Called by the request processor, in its execution thread, every time
277 * a block of data becomes available.
278 * - Request processor performs a synchronous call to handleData() i.e.
279 * its execution threads holds until handleData() returns.
280 * - Original data items are disposed of on return i.e. keep a reference
281 * (or a copy) if some persistence is needed between invocations.
282 * - When there is no more data, done() is called.
283 *
284 * @param data a piece of data
285 */
286 @Override
287 public void handleData(ITmfEvent data) {
288 if (data != null) {
289 fNbRead++;
290 }
291 }
292
293 @Override
294 public void handleStarted() {
295 if (TmfCoreTracer.isRequestTraced()) {
296 TmfCoreTracer.traceRequest(this, "STARTED"); //$NON-NLS-1$
297 }
298 }
299
300 /**
301 * Handle the completion of the request. It is called when there is no
302 * more data available either because:
303 * - the request completed normally
304 * - the request failed
305 * - the request was canceled
306 *
307 * As a convenience, handleXXXX methods are provided. They are meant to be
308 * overridden by the application if it needs to handle these conditions.
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(this, "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(this, "SUCCEEDED"); //$NON-NLS-1$
335 }
336 }
337
338 @Override
339 public void handleFailure() {
340 if (TmfCoreTracer.isRequestTraced()) {
341 TmfCoreTracer.traceRequest(this, "FAILED"); //$NON-NLS-1$
342 }
343 }
344
345 @Override
346 public void handleCancel() {
347 if (TmfCoreTracer.isRequestTraced()) {
348 TmfCoreTracer.traceRequest(this, "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 /**
365 * To suspend the client thread until the request completes (or is
366 * canceled).
367 *
368 * @throws InterruptedException
369 * If the thread was interrupted while waiting
370 */
371 @Override
372 public void waitForCompletion() throws InterruptedException {
373 while (!fRequestCompleted) {
374 completedLatch.await();
375 }
376 }
377
378 /**
379 * Called by the request processor upon starting to service the request.
380 */
381 @Override
382 public void start() {
383 synchronized (this) {
384 fRequestRunning = true;
385 }
386 handleStarted();
387 startedLatch.countDown();
388 }
389
390 /**
391 * Called by the request processor upon completion.
392 */
393 @Override
394 public void done() {
395 synchronized (this) {
396 if (!fRequestCompleted) {
397 fRequestRunning = false;
398 fRequestCompleted = true;
399 } else {
400 return;
401 }
402 }
403 try {
404 handleCompleted();
405 } finally {
406 completedLatch.countDown();
407 }
408 }
409
410 /**
411 * Called by the request processor upon failure.
412 */
413 @Override
414 public void fail() {
415 synchronized (this) {
416 fRequestFailed = true;
417 }
418 done();
419 }
420
421 /**
422 * Called by the request processor upon cancellation.
423 */
424 @Override
425 public void cancel() {
426 synchronized (this) {
427 fRequestCanceled = true;
428 }
429 done();
430 }
431
432 // ------------------------------------------------------------------------
433 // Object
434 // ------------------------------------------------------------------------
435
436 @Override
437 // All requests have a unique id
438 public int hashCode() {
439 return getRequestId();
440 }
441
442 @Override
443 public boolean equals(Object other) {
444 if (other instanceof TmfDataRequest) {
445 TmfDataRequest request = (TmfDataRequest) other;
446 return (request.fDataType == fDataType) && (request.fIndex == fIndex)
447 && (request.fNbRequested == fNbRequested);
448 }
449 return false;
450 }
451
452 @Override
453 @SuppressWarnings("nls")
454 public String toString() {
455 String name = getClass().getName();
456 int dot = name.lastIndexOf('.');
457 if (dot >= 0) {
458 name = name.substring(dot + 1);
459 }
460 return "[" + name + "(" + fRequestId + "," + fDataType.getSimpleName()+ "," + getExecType()
461 + "," + fIndex + "," + fNbRequested + ")]";
462 }
463 }
This page took 0.039746 seconds and 5 git commands to generate.